Decompiled source of Ru Lethal v1.0.0
BepInEx/core/XUnity.Common.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Utils; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Logging; using XUnity.Common.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Common dependencies shared between XUnity Auto Translator and Resource Redirector.")] [assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: AssemblyProduct("XUnity.Common")] [assembly: AssemblyTitle("XUnity.Common")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] namespace XUnity.Common.Utilities { public static class ArrayHelper { public static T[] Null<T>() { return null; } } public static class CabHelper { private static string CreateRandomCab() { return "CAB-" + Guid.NewGuid().ToString("N"); } public static void RandomizeCab(byte[] assetBundleData) { string @string = Encoding.ASCII.GetString(assetBundleData, 0, Math.Min(1024, assetBundleData.Length - 4)); int num = @string.IndexOf("CAB-", StringComparison.Ordinal); if (num >= 0) { int num2 = @string.Substring(num).IndexOf('\0'); if (num2 >= 0 && num2 <= 36) { string s = CreateRandomCab(); Buffer.BlockCopy(Encoding.ASCII.GetBytes(s), 36 - num2, assetBundleData, num, num2); } } } public static void RandomizeCabWithAnyLength(byte[] assetBundleData) { FindAndReplaceCab("CAB-", 0, assetBundleData, 2048); } private static void FindAndReplaceCab(string ansiStringToStartWith, byte byteToEndWith, byte[] data, int maxIterations = -1) { int num = Math.Min(data.Length, maxIterations); if (num == -1) { num = data.Length; } int num2 = 0; int length = ansiStringToStartWith.Length; string text = Guid.NewGuid().ToString("N"); int num3 = 0; for (int i = 0; i < num; i++) { char c = (char)data[i]; if (num2 == length) { while (data[i] != byteToEndWith && i < num) { if (num3 >= text.Length) { num3 = 0; text = Guid.NewGuid().ToString("N"); } data[i++] = (byte)text[num3++]; } break; } num2 = ((c == ansiStringToStartWith[num2]) ? (num2 + 1) : 0); } } } internal static class CecilFastReflectionHelper { private static readonly Type[] DynamicMethodDelegateArgs = new Type[2] { typeof(object), typeof(object[]) }; public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs); ILProcessor iLProcessor = val.GetILProcessor(); ParameterInfo[] parameters = method.GetParameters(); bool flag = true; if (!method.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); if (method.DeclaringType.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, method.DeclaringType); } } for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { iLProcessor.Emit(OpCodes.Ldarg_1); iLProcessor.Emit(OpCodes.Ldc_I4, i); } iLProcessor.Emit(OpCodes.Ldarg_1); iLProcessor.Emit(OpCodes.Ldc_I4, i); if (isByRef && !isValueType) { Extensions.Emit(iLProcessor, OpCodes.Ldelema, typeof(object)); continue; } iLProcessor.Emit(OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, type); if (isByRef) { Extensions.Emit(iLProcessor, OpCodes.Box, type); iLProcessor.Emit(OpCodes.Dup); Extensions.Emit(iLProcessor, OpCodes.Unbox, type); if (flag) { flag = false; val.Definition.Body.Variables.Add(new VariableDefinition((TypeReference)new PinnedType((TypeReference)new PointerType(((MemberReference)val.Definition).Module.TypeSystem.Void)))); } iLProcessor.Emit(OpCodes.Stloc_0); iLProcessor.Emit(OpCodes.Stelem_Ref); iLProcessor.Emit(OpCodes.Ldloc_0); } } else { Extensions.Emit(iLProcessor, OpCodes.Unbox, type); } } if (method.IsConstructor) { Extensions.Emit(iLProcessor, OpCodes.Newobj, (MethodBase)(method as ConstructorInfo)); } else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall) { Extensions.Emit(iLProcessor, OpCodes.Call, (MethodBase)(method as MethodInfo)); } else { Extensions.Emit(iLProcessor, OpCodes.Callvirt, (MethodBase)(method as MethodInfo)); } Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType); if ((object)type2 != typeof(void)) { if (type2.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Box, type2); } } else { iLProcessor.Emit(OpCodes.Ldnull); } iLProcessor.Emit(OpCodes.Ret); return (FastReflectionDelegate)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(FastReflectionDelegate)); } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match return type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) }); ILProcessor iLProcessor = val.GetILProcessor(); if (!fieldInfo.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType); } Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType); } iLProcessor.Emit(OpCodes.Ret); return (Func<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Func<T, F>)); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match argument type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethodDefinition val = new DynamicMethodDefinition("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", (Type)null, new Type[2] { typeof(T), typeof(F) }); ILProcessor iLProcessor = val.GetILProcessor(); if (!fieldInfo.IsStatic) { iLProcessor.Emit(OpCodes.Ldarg_0); Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.DeclaringType); } iLProcessor.Emit(OpCodes.Ldarg_1); if ((object)fieldInfo.FieldType != typeof(F)) { if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { if (fieldInfo.FieldType.IsValueType) { Extensions.Emit(iLProcessor, OpCodes.Unbox_Any, fieldInfo.FieldType); } else { Extensions.Emit(iLProcessor, OpCodes.Box, fieldInfo.FieldType); } } else { Extensions.Emit(iLProcessor, OpCodes.Castclass, fieldInfo.FieldType); } } Extensions.Emit(iLProcessor, fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); iLProcessor.Emit(OpCodes.Ret); return (Action<T, F>)Extensions.CreateDelegate((MethodBase)val.Generate(), typeof(Action<T, F>)); } } public static class CustomFastReflectionHelper { private struct FastReflectionDelegateKey { public MethodBase Method { get; } public bool DirectBoxValueAccess { get; } public bool ForceNonVirtCall { get; } public FastReflectionDelegateKey(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { Method = method; DirectBoxValueAccess = directBoxValueAccess; ForceNonVirtCall = forceNonVirtCall; } public override bool Equals(object obj) { if (obj is FastReflectionDelegateKey fastReflectionDelegateKey && EqualityComparer<MethodBase>.Default.Equals(Method, fastReflectionDelegateKey.Method) && DirectBoxValueAccess == fastReflectionDelegateKey.DirectBoxValueAccess) { return ForceNonVirtCall == fastReflectionDelegateKey.ForceNonVirtCall; } return false; } public override int GetHashCode() { return ((1017116076 * -1521134295 + EqualityComparer<MethodBase>.Default.GetHashCode(Method)) * -1521134295 + DirectBoxValueAccess.GetHashCode()) * -1521134295 + ForceNonVirtCall.GetHashCode(); } } private static readonly Dictionary<FastReflectionDelegateKey, FastReflectionDelegate> MethodCache = new Dictionary<FastReflectionDelegateKey, FastReflectionDelegate>(); public static FastReflectionDelegate CreateFastDelegate(this MethodBase method, bool directBoxValueAccess = true, bool forceNonVirtCall = false) { FastReflectionDelegateKey key = new FastReflectionDelegateKey(method, directBoxValueAccess, forceNonVirtCall); if (MethodCache.TryGetValue(key, out var value)) { return value; } value = (((object)ClrTypes.DynamicMethodDefinition == null) ? GetFastDelegateForSRE(method, directBoxValueAccess, forceNonVirtCall) : GetFastDelegateForCecil(method, directBoxValueAccess, forceNonVirtCall)); MethodCache.Add(key, value); return value; } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { if ((object)ClrTypes.DynamicMethodDefinition != null) { return CreateFastFieldGetterForCecil<T, F>(fieldInfo); } return CreateFastFieldGetterForSRE<T, F>(fieldInfo); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { if ((object)ClrTypes.DynamicMethodDefinition != null) { return CreateFastFieldSetterForCecil<T, F>(fieldInfo); } return CreateFastFieldSetterForSRE<T, F>(fieldInfo); } private static FastReflectionDelegate GetFastDelegateForCecil(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { try { return CecilFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (object target, object[] args) => method.Invoke(target, args); } } } private static Func<T, F> CreateFastFieldGetterForCecil<T, F>(FieldInfo fieldInfo) { try { return CecilFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (T target) => (F)fieldInfo.GetValue(target); } } } private static Action<T, F> CreateFastFieldSetterForCecil<T, F>(FieldInfo fieldInfo) { try { return CecilFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e) { try { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with cecil. Retrying with reflection emit..."); return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e2) { XuaLogger.Common.Warn(e2, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return delegate(T target, F value) { fieldInfo.SetValue(target, value); }; } } } private static FastReflectionDelegate GetFastDelegateForSRE(MethodBase method, bool directBoxValueAccess, bool forceNonVirtCall) { try { return ReflectionEmitFastReflectionHelper.CreateFastDelegate(method, directBoxValueAccess, forceNonVirtCall); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (object target, object[] args) => method.Invoke(target, args); } } private static Func<T, F> CreateFastFieldGetterForSRE<T, F>(FieldInfo fieldInfo) { try { return ReflectionEmitFastReflectionHelper.CreateFastFieldGetter<T, F>(fieldInfo); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return (T target) => (F)fieldInfo.GetValue(target); } } private static Action<T, F> CreateFastFieldSetterForSRE<T, F>(FieldInfo fieldInfo) { try { return ReflectionEmitFastReflectionHelper.CreateFastFieldSetter<T, F>(fieldInfo); } catch (Exception e) { XuaLogger.Common.Warn(e, "Failed creating fast reflection delegate through with reflection emit. Falling back to standard reflection..."); return delegate(T target, F value) { fieldInfo.SetValue(target, value); }; } } } public static class DiacriticHelper { public static string RemoveAllDiacritics(this string input) { return new string((from c in input.SafeNormalize(NormalizationForm.FormD) where CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark select c).ToArray()).SafeNormalize(); } private static string SafeNormalize(this string input, NormalizationForm normalizationForm = NormalizationForm.FormC) { return ReplaceNonCharacters(input, '?').Normalize(normalizationForm); } private static string ReplaceNonCharacters(string input, char replacement) { StringBuilder stringBuilder = new StringBuilder(input.Length); for (int i = 0; i < input.Length; i++) { if (char.IsSurrogatePair(input, i)) { int num = char.ConvertToUtf32(input, i); i++; if (IsValidCodePoint(num)) { stringBuilder.Append(char.ConvertFromUtf32(num)); } else { stringBuilder.Append(replacement); } } else { char c = input[i]; if (IsValidCodePoint(c)) { stringBuilder.Append(c); } else { stringBuilder.Append(replacement); } } } return stringBuilder.ToString(); } private static bool IsValidCodePoint(int point) { if (point >= 64976) { if (point >= 65008 && (point & 0xFFFF) != 65535 && (point & 0xFFFE) != 65534) { return point <= 1114111; } return false; } return true; } } public static class ExpressionHelper { public static Delegate CreateTypedFastInvoke(MethodBase method) { if ((object)method == null) { throw new ArgumentNullException("method"); } return CreateTypedFastInvokeUnchecked(method); } public static Delegate CreateTypedFastInvokeUnchecked(MethodBase method) { if ((object)method == null) { return null; } if (method.IsGenericMethod) { throw new ArgumentException("The provided method must not be generic.", "method"); } if (method is MethodInfo methodInfo) { Expression[] arguments; if (method.IsStatic) { ParameterExpression[] array = (from p in methodInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToArray(); arguments = array; return Expression.Lambda(Expression.Call(null, methodInfo, arguments), array).Compile(); } List<ParameterExpression> list = (from p in methodInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToList(); list.Insert(0, Expression.Parameter(methodInfo.DeclaringType, "instance")); ParameterExpression instance = list[0]; arguments = list.Skip(1).ToArray(); return Expression.Lambda(Expression.Call(instance, methodInfo, arguments), list.ToArray()).Compile(); } if (method is ConstructorInfo constructorInfo) { ParameterExpression[] array2 = (from p in constructorInfo.GetParameters() select Expression.Parameter(p.ParameterType, p.Name)).ToArray(); Expression[] arguments = array2; return Expression.Lambda(Expression.New(constructorInfo, arguments), array2).Compile(); } throw new ArgumentException("method", "This method only supports MethodInfo and ConstructorInfo."); } } public static class ExtensionDataHelper { private static readonly object Sync; private static readonly WeakDictionary<object, object> WeakDynamicFields; public static int WeakReferenceCount { get { lock (Sync) { return WeakDynamicFields.Count; } } } static ExtensionDataHelper() { Sync = new object(); WeakDynamicFields = new WeakDictionary<object, object>(); MaintenanceHelper.AddMaintenanceFunction(Cull, 12); } public static void SetExtensionData<T>(this object obj, T t) { lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary) { dictionary[typeof(T)] = t; return; } Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>(); dictionary2.Add(value.GetType(), value); dictionary2[typeof(T)] = t; WeakDynamicFields[obj] = dictionary2; } else { WeakDynamicFields[obj] = t; } } } public static T GetOrCreateExtensionData<T>(this object obj) where T : new() { if (obj == null) { return default(T); } lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary) { if (dictionary.TryGetValue(typeof(T), out value)) { return (T)value; } T val = new T(); dictionary[typeof(T)] = val; return val; } if (!(value is T result)) { Dictionary<Type, object> dictionary2 = new Dictionary<Type, object>(); dictionary2.Add(value.GetType(), value); T val2 = new T(); dictionary2[typeof(T)] = val2; WeakDynamicFields[obj] = dictionary2; return val2; } return result; } T val3 = new T(); WeakDynamicFields[obj] = val3; return val3; } } public static T GetExtensionData<T>(this object obj) { if (obj == null) { return default(T); } lock (Sync) { if (WeakDynamicFields.TryGetValue(obj, out var value)) { if (value is Dictionary<Type, object> dictionary && dictionary.TryGetValue(typeof(T), out value)) { if (!(value is T result)) { return default(T); } return result; } if (!(value is T result2)) { return default(T); } return result2; } } return default(T); } public static void Cull() { lock (Sync) { WeakDynamicFields.RemoveCollectedEntries(); } } public static List<KeyValuePair<object, object>> GetAllRegisteredObjects() { lock (Sync) { return IterateAllPairs().ToList(); } } public static void Remove(object obj) { lock (Sync) { WeakDynamicFields.Remove(obj); } } private static IEnumerable<KeyValuePair<object, object>> IterateAllPairs() { foreach (KeyValuePair<object, object> kvp in WeakDynamicFields) { if (kvp.Value is Dictionary<Type, object> dictionary) { foreach (KeyValuePair<Type, object> item in dictionary) { yield return new KeyValuePair<object, object>(kvp.Key, item.Value); } } else { yield return kvp; } } } } public delegate object FastReflectionDelegate(object target, params object[] args); public static class HookingHelper { private static readonly MethodInfo PatchMethod12; private static readonly MethodInfo PatchMethod20; private static readonly object Harmony; private static bool _loggedHarmonyError; static HookingHelper() { PatchMethod12 = ClrTypes.HarmonyInstance?.GetMethod("Patch", new Type[4] { ClrTypes.MethodBase, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod }); PatchMethod20 = ClrTypes.Harmony?.GetMethod("Patch", new Type[5] { ClrTypes.MethodBase, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod, ClrTypes.HarmonyMethod }); _loggedHarmonyError = false; try { if ((object)ClrTypes.HarmonyInstance != null) { Harmony = ClrTypes.HarmonyInstance.GetMethod("Create", BindingFlags.Static | BindingFlags.Public).Invoke(null, new object[1] { "xunity.common.hookinghelper" }); } else if ((object)ClrTypes.Harmony != null) { Harmony = ClrTypes.Harmony.GetConstructor(new Type[1] { typeof(string) }).Invoke(new object[1] { "xunity.common.hookinghelper" }); } else { XuaLogger.Common.Error("An unexpected exception occurred during harmony initialization, likely caused by unknown Harmony version. Harmony hooks will be unavailable!"); } } catch (Exception e) { XuaLogger.Common.Error(e, "An unexpected exception occurred during harmony initialization. Harmony hooks will be unavailable!"); } } public static void PatchAll(IEnumerable<Type> types, bool forceExternHooks) { foreach (Type type in types) { PatchType(type, forceExternHooks); } } public static void PatchAll(IEnumerable<Type[]> types, bool forceMonoModHooks) { foreach (Type[] type in types) { for (int i = 0; i < type.Length && !PatchType(type[i], forceMonoModHooks); i++) { } } } public static bool PatchType(Type type, bool forceExternHooks) { MethodBase methodBase = null; IntPtr intPtr = IntPtr.Zero; try { if (Harmony == null && !_loggedHarmonyError) { _loggedHarmonyError = true; XuaLogger.Common.Warn("Harmony is not loaded or could not be initialized. Using fallback hooks instead."); } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = type.GetMethod("Prepare", bindingAttr); if ((object)method == null || (bool)method.Invoke(null, new object[1] { Harmony })) { try { methodBase = (MethodBase)(type.GetMethod("TargetMethod", bindingAttr)?.Invoke(null, new object[1] { Harmony })); } catch { } try { intPtr = ((IntPtr?)type.GetMethod("TargetMethodPointer", bindingAttr)?.Invoke(null, null)) ?? IntPtr.Zero; } catch { } if ((object)methodBase == null && intPtr == IntPtr.Zero) { if ((object)methodBase != null) { XuaLogger.Common.Warn("Could not hook '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Likely due differences between different versions of the engine or text framework."); } else { XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); } return false; } MethodInfo method2 = type.GetMethod("Prefix", bindingAttr); MethodInfo method3 = type.GetMethod("Postfix", bindingAttr); MethodInfo method4 = type.GetMethod("Finalizer", bindingAttr); if ((object)methodBase == null || forceExternHooks || Harmony == null || ((object)method2 == null && (object)method3 == null && (object)method4 == null)) { return PatchWithExternHooks(type, methodBase, intPtr, forced: true); } if ((object)methodBase != null) { try { int? priority = type.GetCustomAttributes(typeof(HookingHelperPriorityAttribute), inherit: false).OfType<HookingHelperPriorityAttribute>().FirstOrDefault()?.priority; object obj3 = (((object)method2 != null) ? CreateHarmonyMethod(method2, priority) : null); object obj4 = (((object)method3 != null) ? CreateHarmonyMethod(method3, priority) : null); object obj5 = (((object)method4 != null) ? CreateHarmonyMethod(method4, priority) : null); if ((object)PatchMethod12 != null) { PatchMethod12.Invoke(Harmony, new object[4] { methodBase, obj3, obj4, null }); } else { PatchMethod20.Invoke(Harmony, new object[5] { methodBase, obj3, obj4, null, obj5 }); } XuaLogger.Common.Debug("Hooked " + methodBase.DeclaringType.FullName + "." + methodBase.Name + " through Harmony hooks."); return true; } catch (Exception e) when (((Func<bool>)delegate { // Could not convert BlockContainer to single expression System.Runtime.CompilerServices.Unsafe.SkipInit(out int num); if (e.FirstInnerExceptionOfType<PlatformNotSupportedException>() == null) { ArgumentException ex = e.FirstInnerExceptionOfType<ArgumentException>(); num = ((ex != null && ex.Message?.Contains("no body") == true) ? 1 : 0); } else { num = 1; } return num != 0; }).Invoke()) { return PatchWithExternHooks(type, methodBase, intPtr, forced: false); } } XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); } } catch (Exception e2) { if ((object)methodBase != null) { XuaLogger.Common.Warn(e2, "An error occurred while patching property/method '" + methodBase.DeclaringType.FullName + "." + methodBase.Name + "'. Failing hook: '" + type.Name + "'."); } else { XuaLogger.Common.Warn(e2, "An error occurred while patching property/method. Failing hook: '" + type.Name + "'."); } } return false; } private static bool PatchWithExternHooks(Type type, MethodBase original, IntPtr originalPtr, bool forced) { BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; if ((object)ClrTypes.Imports != null) { if (originalPtr == IntPtr.Zero) { XuaLogger.Common.Warn("Could not hook '" + type.Name + "'. Likely due differences between different versions of the engine or text framework."); return false; } IntPtr? intPtr = type.GetMethod("ML_Detour", bindingAttr)?.MethodHandle.GetFunctionPointer(); if (intPtr.HasValue && intPtr.Value != IntPtr.Zero) { ClrTypes.Imports.GetMethod("Hook", bindingAttr).Invoke(null, new object[2] { originalPtr, intPtr.Value }); XuaLogger.Common.Debug("Hooked " + type.Name + " through MelonMod Imports.Hook method."); return true; } XuaLogger.Common.Warn("Could not hook '" + type.Name + "' because no detour method was found."); } else { if ((object)original == null) { XuaLogger.Common.Warn("Cannot hook '" + type.Name + "'. Could not locate the original method. Failing hook: '" + type.Name + "'."); return false; } if ((object)ClrTypes.Hook == null || (object)ClrTypes.NativeDetour == null) { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. MonoMod hooks is not supported in this runtime as MonoMod is not loaded. Failing hook: '" + type.Name + "'."); return false; } object obj = type.GetMethod("Get_MM_Detour", bindingAttr)?.Invoke(null, null) ?? type.GetMethod("MM_Detour", bindingAttr); if (obj != null) { string text = "(managed)"; object obj2; try { obj2 = ClrTypes.Hook.GetConstructor(new Type[2] { typeof(MethodBase), typeof(MethodInfo) }).Invoke(new object[2] { original, obj }); obj2.GetType().GetMethod("Apply").Invoke(obj2, null); } catch (Exception e) when (((Func<bool>)delegate { // Could not convert BlockContainer to single expression System.Runtime.CompilerServices.Unsafe.SkipInit(out int num); if (e.FirstInnerExceptionOfType<NullReferenceException>() == null) { NotSupportedException ex = e.FirstInnerExceptionOfType<NotSupportedException>(); num = ((ex != null && ex.Message?.Contains("Body-less") == true) ? 1 : 0); } else { num = 1; } return num != 0; }).Invoke()) { text = "(native)"; obj2 = ClrTypes.NativeDetour.GetConstructor(new Type[2] { typeof(MethodBase), typeof(MethodBase) }).Invoke(new object[2] { original, obj }); obj2.GetType().GetMethod("Apply").Invoke(obj2, null); } type.GetMethod("MM_Init", bindingAttr)?.Invoke(null, new object[1] { obj2 }); if (forced) { XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through forced MonoMod hooks. " + text); } else { XuaLogger.Common.Debug("Hooked " + original.DeclaringType.FullName + "." + original.Name + " through MonoMod hooks. " + text); } return true; } if (forced) { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'."); } else { XuaLogger.Common.Warn("Cannot hook '" + original.DeclaringType.FullName + "." + original.Name + "'. Harmony is not supported in this runtime and no alternate MonoMod hook has been implemented. Failing hook: '" + type.Name + "'."); } } return false; } private static object CreateHarmonyMethod(MethodInfo method, int? priority) { object obj = ClrTypes.HarmonyMethod.GetConstructor(new Type[1] { typeof(MethodInfo) }).Invoke(new object[1] { method }); if (priority.HasValue) { (ClrTypes.HarmonyMethod.GetField("priority", BindingFlags.Instance | BindingFlags.Public) ?? ClrTypes.HarmonyMethod.GetField("prioritiy", BindingFlags.Instance | BindingFlags.Public)).SetValue(obj, priority.Value); } return obj; } } public class HookingHelperPriorityAttribute : Attribute { public int priority; public HookingHelperPriorityAttribute(int priority) { this.priority = priority; } } public static class HookPriority { public const int Last = 0; public const int VeryLow = 100; public const int Low = 200; public const int LowerThanNormal = 300; public const int Normal = 400; public const int HigherThanNormal = 500; public const int High = 600; public const int VeryHigh = 700; public const int First = 800; } public static class ListExtensions { public static void BinarySearchInsert<T>(this List<T> items, T item) where T : IComparable<T> { int num = items.BinarySearch(item); if (num < 0) { items.Insert(~num, item); } else { items.Insert(num, item); } } } public static class MaintenanceHelper { private class ActionRegistration { public Action Action { get; } public int Filter { get; } public ActionRegistration(Action action, int filter) { Action = action; Filter = filter; } } private static readonly object Sync = new object(); private static readonly List<ActionRegistration> RegisteredActions = new List<ActionRegistration>(); private static bool _initialized; public static void AddMaintenanceFunction(Action action, int filter) { lock (Sync) { if (!_initialized) { _initialized = true; StartMaintenance(); } ActionRegistration item = new ActionRegistration(action, filter); RegisteredActions.Add(item); } } private static void StartMaintenance() { Thread thread = new Thread(MaintenanceLoop); thread.IsBackground = true; thread.Start(); } private static void MaintenanceLoop(object state) { int num = 0; while (true) { lock (Sync) { foreach (ActionRegistration registeredAction in RegisteredActions) { if (num % registeredAction.Filter == 0) { try { registeredAction.Action(); } catch (Exception e) { XuaLogger.Common.Error(e, "An unexpected error occurred during maintenance."); } } } } num++; Thread.Sleep(5000); } } } public static class Paths { private static string _gameRoot; public static string GameRoot { get { return _gameRoot ?? GetAndSetGameRoot(); } set { _gameRoot = value; } } public static void Initialize() { GetAndSetGameRoot(); } private static string GetAndSetGameRoot() { return _gameRoot = new DirectoryInfo(Application.dataPath).Parent.FullName; } } public static class ReflectionCache { private struct MemberLookupKey { public Type Type { get; set; } public string MemberName { get; set; } public MemberLookupKey(Type type, string memberName) { Type = type; MemberName = memberName; } public override bool Equals(object obj) { if (obj is MemberLookupKey memberLookupKey) { if ((object)Type == memberLookupKey.Type) { return MemberName == memberLookupKey.MemberName; } return false; } return false; } public override int GetHashCode() { return Type.GetHashCode() + MemberName.GetHashCode(); } } private static Dictionary<MemberLookupKey, CachedMethod> Methods = new Dictionary<MemberLookupKey, CachedMethod>(); private static Dictionary<MemberLookupKey, CachedProperty> Properties = new Dictionary<MemberLookupKey, CachedProperty>(); private static Dictionary<MemberLookupKey, CachedField> Fields = new Dictionary<MemberLookupKey, CachedField>(); public static CachedMethod CachedMethod(this Type type, string name) { return type.CachedMethod(name, (Type[])null); } public static CachedMethod CachedMethod(this Type type, string name, params Type[] types) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Methods.TryGetValue(key, out var value)) { Type type2 = type; MethodInfo methodInfo = null; while ((object)methodInfo == null && (object)type2 != null) { methodInfo = ((types != null && types.Length != 0) ? type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null) : type2.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); type2 = type2.BaseType; } if ((object)methodInfo != null) { value = new CachedMethod(methodInfo); } Methods[key] = value; } return value; } public static CachedProperty CachedProperty(this Type type, string name) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Properties.TryGetValue(key, out var value)) { Type type2 = type; PropertyInfo propertyInfo = null; while ((object)propertyInfo == null && (object)type2 != null) { propertyInfo = type2.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } if ((object)propertyInfo != null) { value = new CachedProperty(propertyInfo); } Properties[key] = value; } return value; } public static CachedField CachedField(this Type type, string name) { MemberLookupKey key = new MemberLookupKey(type, name); if (!Fields.TryGetValue(key, out var value)) { Type type2 = type; FieldInfo fieldInfo = null; while ((object)fieldInfo == null && (object)type2 != null) { fieldInfo = type2.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); type2 = type2.BaseType; } if ((object)fieldInfo != null) { value = new CachedField(fieldInfo); } Fields[key] = value; } return value; } public static CachedField CachedFieldByIndex(this Type type, int index, Type fieldType, BindingFlags flags) { FieldInfo[] array = (from x in type.GetFields(flags) where (object)x.FieldType == fieldType select x).ToArray(); if (index < array.Length) { return new CachedField(array[index]); } return null; } } public class CachedMethod { private static readonly object[] Args0 = new object[0]; private static readonly object[] Args1 = new object[1]; private static readonly object[] Args2 = new object[2]; private FastReflectionDelegate _invoke; internal CachedMethod(MethodInfo method) { _invoke = method.CreateFastDelegate(); } public object Invoke(object instance, object[] arguments) { return _invoke(instance, arguments); } public object Invoke(object instance) { return _invoke(instance, Args0); } public object Invoke(object instance, object arg1) { try { Args1[0] = arg1; return _invoke(instance, Args1); } finally { Args1[0] = null; } } public object Invoke(object instance, object arg1, object arg2) { try { Args2[0] = arg1; Args2[1] = arg2; return _invoke(instance, Args2); } finally { Args2[0] = null; Args2[1] = null; } } } public class CachedProperty { private static readonly object[] Args0 = new object[0]; private static readonly object[] Args1 = new object[1]; private FastReflectionDelegate _set; private FastReflectionDelegate _get; public Type PropertyType { get; } internal CachedProperty(PropertyInfo propertyInfo) { if (propertyInfo.CanRead) { _get = propertyInfo.GetGetMethod(nonPublic: true).CreateFastDelegate(); } if (propertyInfo.CanWrite) { _set = propertyInfo.GetSetMethod(nonPublic: true).CreateFastDelegate(); } PropertyType = propertyInfo.PropertyType; } public void Set(object instance, object[] arguments) { if (_set != null) { _set(instance, arguments); } } public void Set(object instance, object arg1) { if (_set == null) { return; } try { Args1[0] = arg1; _set(instance, Args1); } finally { Args1[0] = null; } } public object Get(object instance, object[] arguments) { if (_get == null) { return null; } return _get(instance, arguments); } public object Get(object instance) { if (_get == null) { return null; } return _get(instance, Args0); } } public class CachedField { private Func<object, object> _get; private Action<object, object> _set; public Type FieldType { get; } internal CachedField(FieldInfo fieldInfo) { _get = CustomFastReflectionHelper.CreateFastFieldGetter<object, object>(fieldInfo); _set = CustomFastReflectionHelper.CreateFastFieldSetter<object, object>(fieldInfo); FieldType = fieldInfo.FieldType; } public void Set(object instance, object value) { if (_set != null) { _set(instance, value); } } public object Get(object instance) { if (_get == null) { return null; } return _get(instance); } } internal static class ReflectionEmitFastReflectionHelper { private static readonly Type[] DynamicMethodDelegateArgs = new Type[2] { typeof(object), typeof(object[]) }; public static FastReflectionDelegate CreateFastDelegate(MethodBase method, bool directBoxValueAccess, bool forceNonVirtcall) { DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + method.DeclaringType.FullName + "." + method.Name + ">", typeof(object), DynamicMethodDelegateArgs, method.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); ParameterInfo[] parameters = method.GetParameters(); bool flag = true; if (!method.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); if (method.DeclaringType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, method.DeclaringType); } } for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; bool isByRef = type.IsByRef; if (isByRef) { type = type.GetElementType(); } bool isValueType = type.IsValueType; if (isByRef && isValueType && !directBoxValueAccess) { iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4, i); } iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4, i); if (isByRef && !isValueType) { iLGenerator.Emit(OpCodes.Ldelema, typeof(object)); continue; } iLGenerator.Emit(OpCodes.Ldelem_Ref); if (!isValueType) { continue; } if (!isByRef || !directBoxValueAccess) { iLGenerator.Emit(OpCodes.Unbox_Any, type); if (isByRef) { iLGenerator.Emit(OpCodes.Box, type); iLGenerator.Emit(OpCodes.Dup); iLGenerator.Emit(OpCodes.Unbox, type); if (flag) { flag = false; throw new NotImplementedException("No idea how to implement this..."); } iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Stelem_Ref); iLGenerator.Emit(OpCodes.Ldloc_0); } } else { iLGenerator.Emit(OpCodes.Unbox, type); } } if (method.IsConstructor) { iLGenerator.Emit(OpCodes.Newobj, method as ConstructorInfo); } else if (method.IsFinal || !method.IsVirtual || forceNonVirtcall) { iLGenerator.Emit(OpCodes.Call, method as MethodInfo); } else { iLGenerator.Emit(OpCodes.Callvirt, method as MethodInfo); } Type type2 = (method.IsConstructor ? method.DeclaringType : (method as MethodInfo).ReturnType); if ((object)type2 != typeof(void)) { if (type2.IsValueType) { iLGenerator.Emit(OpCodes.Box, type2); } } else { iLGenerator.Emit(OpCodes.Ldnull); } iLGenerator.Emit(OpCodes.Ret); return (FastReflectionDelegate)dynamicMethod.CreateDelegate(typeof(FastReflectionDelegate)); } public static Func<T, F> CreateFastFieldGetter<T, F>(FieldInfo fieldInfo) { if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match return type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Get_" + fieldInfo.Name + ">", typeof(F), new Type[1] { typeof(T) }, fieldInfo.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!fieldInfo.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); } iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } iLGenerator.Emit(OpCodes.Ret); return (Func<T, F>)dynamicMethod.CreateDelegate(typeof(Func<T, F>)); } public static Action<T, F> CreateFastFieldSetter<T, F>(FieldInfo fieldInfo) { if ((object)fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } if (!typeof(F).IsAssignableFrom(fieldInfo.FieldType)) { throw new ArgumentException("FieldInfo type does not match argument type."); } if ((object)typeof(T) != typeof(object) && ((object)fieldInfo.DeclaringType == null || !fieldInfo.DeclaringType.IsAssignableFrom(typeof(T)))) { throw new MissingFieldException(typeof(T).Name, fieldInfo.Name); } DynamicMethod dynamicMethod = new DynamicMethod("FastReflection<" + typeof(T).FullName + ".Set_" + fieldInfo.Name + ">", null, new Type[2] { typeof(T), typeof(F) }, fieldInfo.DeclaringType.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!fieldInfo.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); } iLGenerator.Emit(OpCodes.Ldarg_1); if ((object)fieldInfo.FieldType != typeof(F)) { if (fieldInfo.FieldType.IsValueType != typeof(F).IsValueType) { if (fieldInfo.FieldType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox, fieldInfo.FieldType); } else { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } } else { iLGenerator.Emit(OpCodes.Castclass, fieldInfo.FieldType); } } iLGenerator.Emit(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ret); return (Action<T, F>)dynamicMethod.CreateDelegate(typeof(Action<T, F>)); } } public static class TimeHelper { public static float realtimeSinceStartup => Time.realtimeSinceStartup; } public class UnityObjectReferenceComparer : IEqualityComparer<object> { public static readonly UnityObjectReferenceComparer Default = new UnityObjectReferenceComparer(); public new bool Equals(object x, object y) { return x == y; } public int GetHashCode(object obj) { return obj.GetHashCode(); } } public class WeakReference<T> : WeakReference where T : class { public new T Target => (T)base.Target; public static WeakReference<T> Create(T target) { if (target == null) { return WeakNullReference<T>.Singleton; } return new WeakReference<T>(target); } protected WeakReference(T target) : base(target, trackResurrection: false) { } } internal class WeakNullReference<T> : WeakReference<T> where T : class { public static readonly WeakNullReference<T> Singleton = new WeakNullReference<T>(); public override bool IsAlive => true; private WeakNullReference() : base((T)null) { } } internal sealed class WeakKeyReference<T> : WeakReference<T> where T : class { public readonly int HashCode; public WeakKeyReference(T key, WeakKeyComparer<T> comparer) : base(key) { HashCode = comparer.GetHashCode(key); } } internal sealed class WeakKeyComparer<T> : IEqualityComparer<object> where T : class { private IEqualityComparer<T> comparer; internal WeakKeyComparer(IEqualityComparer<T> comparer) { if (comparer == null) { comparer = EqualityComparer<T>.Default; } this.comparer = comparer; } public int GetHashCode(object obj) { if (obj is WeakKeyReference<T> weakKeyReference) { return weakKeyReference.HashCode; } return comparer.GetHashCode((T)obj); } public new bool Equals(object x, object y) { bool isDead; T target = GetTarget(x, out isDead); bool isDead2; T target2 = GetTarget(y, out isDead2); if (isDead) { if (!isDead2) { return false; } return x == y; } if (isDead2) { return false; } return comparer.Equals(target, target2); } private static T GetTarget(object obj, out bool isDead) { T result; if (obj is WeakKeyReference<T> weakKeyReference) { result = weakKeyReference.Target; isDead = !weakKeyReference.IsAlive; } else { result = (T)obj; isDead = false; } return result; } } public sealed class WeakDictionary<TKey, TValue> : BaseDictionary<TKey, TValue> where TKey : class { private Dictionary<object, TValue> dictionary; private WeakKeyComparer<TKey> comparer; public override int Count => dictionary.Count; public WeakDictionary() : this(0, (IEqualityComparer<TKey>)null) { } public WeakDictionary(int capacity) : this(capacity, (IEqualityComparer<TKey>)null) { } public WeakDictionary(IEqualityComparer<TKey> comparer) : this(0, comparer) { } public WeakDictionary(int capacity, IEqualityComparer<TKey> comparer) { this.comparer = new WeakKeyComparer<TKey>(comparer); dictionary = new Dictionary<object, TValue>(capacity, this.comparer); } public override void Add(TKey key, TValue value) { if (key == null) { throw new ArgumentNullException("key"); } WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer); dictionary.Add(key2, value); } public override bool ContainsKey(TKey key) { return dictionary.ContainsKey(key); } public override bool Remove(TKey key) { return dictionary.Remove(key); } public override bool TryGetValue(TKey key, out TValue value) { if (dictionary.TryGetValue(key, out value)) { return true; } value = default(TValue); return false; } protected override void SetValue(TKey key, TValue value) { WeakReference<TKey> key2 = new WeakKeyReference<TKey>(key, comparer); dictionary[key2] = value; } public override void Clear() { dictionary.Clear(); } public override IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { foreach (KeyValuePair<object, TValue> item in dictionary) { WeakReference<TKey> obj = (WeakReference<TKey>)item.Key; TValue value = item.Value; TKey target = obj.Target; if (obj.IsAlive) { yield return new KeyValuePair<TKey, TValue>(target, value); } } } public void RemoveCollectedEntries() { List<object> list = null; foreach (KeyValuePair<object, TValue> item in dictionary) { WeakReference<TKey> weakReference = (WeakReference<TKey>)item.Key; if (!weakReference.IsAlive) { if (list == null) { list = new List<object>(); } list.Add(weakReference); } } if (list == null) { return; } foreach (object item2 in list) { dictionary.Remove(item2); } } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] public abstract class BaseDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable { private abstract class Collection<T> : ICollection<T>, IEnumerable<T>, IEnumerable { protected readonly IDictionary<TKey, TValue> dictionary; public int Count => dictionary.Count; public bool IsReadOnly => true; protected Collection(IDictionary<TKey, TValue> dictionary) { this.dictionary = dictionary; } public void CopyTo(T[] array, int arrayIndex) { BaseDictionary<TKey, TValue>.Copy((ICollection<T>)this, array, arrayIndex); } public virtual bool Contains(T item) { using (IEnumerator<T> enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { T current = enumerator.Current; if (EqualityComparer<T>.Default.Equals(current, item)) { return true; } } } return false; } public IEnumerator<T> GetEnumerator() { foreach (KeyValuePair<TKey, TValue> item in dictionary) { yield return GetItem(item); } } protected abstract T GetItem(KeyValuePair<TKey, TValue> pair); public bool Remove(T item) { throw new NotSupportedException("Collection is read-only."); } public void Add(T item) { throw new NotSupportedException("Collection is read-only."); } public void Clear() { throw new NotSupportedException("Collection is read-only."); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryKeyCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] private class KeyCollection : Collection<TKey> { public KeyCollection(IDictionary<TKey, TValue> dictionary) : base(dictionary) { } protected override TKey GetItem(KeyValuePair<TKey, TValue> pair) { return pair.Key; } public override bool Contains(TKey item) { return dictionary.ContainsKey(item); } } [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy("System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView`2,mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089")] private class ValueCollection : Collection<TValue> { public ValueCollection(IDictionary<TKey, TValue> dictionary) : base(dictionary) { } protected override TValue GetItem(KeyValuePair<TKey, TValue> pair) { return pair.Value; } } private const string PREFIX = "System.Collections.Generic.Mscorlib_"; private const string SUFFIX = ",mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"; private KeyCollection keys; private ValueCollection values; public abstract int Count { get; } public bool IsReadOnly => false; public ICollection<TKey> Keys { get { if (keys == null) { keys = new KeyCollection(this); } return keys; } } public ICollection<TValue> Values { get { if (values == null) { values = new ValueCollection(this); } return values; } } public TValue this[TKey key] { get { if (!TryGetValue(key, out var value)) { throw new KeyNotFoundException(); } return value; } set { SetValue(key, value); } } public abstract void Clear(); public abstract void Add(TKey key, TValue value); public abstract bool ContainsKey(TKey key); public abstract bool Remove(TKey key); public abstract bool TryGetValue(TKey key, out TValue value); public abstract IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator(); protected abstract void SetValue(TKey key, TValue value); public void Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } public bool Contains(KeyValuePair<TKey, TValue> item) { if (!TryGetValue(item.Key, out var value)) { return false; } return EqualityComparer<TValue>.Default.Equals(value, item.Value); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { Copy(this, array, arrayIndex); } public bool Remove(KeyValuePair<TKey, TValue> item) { if (!Contains(item)) { return false; } return Remove(item.Key); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static void Copy<T>(ICollection<T> source, T[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0 || arrayIndex > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex"); } if (array.Length - arrayIndex < source.Count) { throw new ArgumentException("Destination array is not large enough. Check array.Length and arrayIndex."); } foreach (T item in source) { array[arrayIndex++] = item; } } } } namespace XUnity.Common.MonoMod { public static class DetourExtensions { public static T GenerateTrampolineEx<T>(this object detour) { return (T)(from x in detour.GetType().GetMethods() where x.Name == "GenerateTrampoline" && x.IsGenericMethod select x).FirstOrDefault().MakeGenericMethod(typeof(T)).Invoke(detour, null); } } } namespace XUnity.Common.Logging { internal class ConsoleLogger : XuaLogger { public ConsoleLogger(string source) : base(source) { } protected override void Log(LogLevel level, string message) { Console.WriteLine(GetDefaultPrefix(level) + " " + message); } } public enum LogLevel { Debug, Info, Warn, Error } internal class ModLoaderSpecificLogger : XuaLogger { public static class BepInExLogLevel { public const int None = 0; public const int Fatal = 1; public const int Error = 2; public const int Warning = 4; public const int Message = 8; public const int Info = 16; public const int Debug = 32; public const int All = 63; } private static Action<LogLevel, string> _logMethod; public ModLoaderSpecificLogger(string source) : base(source) { if (_logMethod != null) { return; } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public; BindingFlags bindingAttr2 = BindingFlags.Instance | BindingFlags.Public; Type type = Type.GetType("BepInEx.Logging.LogLevel, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.LogLevel, BepInEx.Core", throwOnError: false); if ((object)type != null) { if ((object)(Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.ManualLogSource, BepInEx.Core", throwOnError: false)) != null) { MethodInfo method = (Type.GetType("BepInEx.Logging.Logger, BepInEx", throwOnError: false) ?? Type.GetType("BepInEx.Logging.Logger, BepInEx.Core", throwOnError: false)).GetMethod("CreateLogSource", bindingAttr, null, new Type[1] { typeof(string) }, null); object logInstance2 = method.Invoke(null, new object[1] { base.Source }); MethodInfo method2 = logInstance2.GetType().GetMethod("Log", bindingAttr2, null, new Type[2] { type, typeof(object) }, null); FastReflectionDelegate log2 = method2.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { int num2 = Convert(level); log2(logInstance2, num2, msg); }; } else { Type type2 = Type.GetType("BepInEx.Logger, BepInEx", throwOnError: false); object logInstance = type2.GetProperty("CurrentLogger", bindingAttr).GetValue(null, null); MethodInfo method3 = logInstance.GetType().GetMethod("Log", bindingAttr2, null, new Type[2] { type, typeof(object) }, null); FastReflectionDelegate log = method3.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { int num = Convert(level); log(logInstance, num, msg); }; } } else { Type type3 = Type.GetType("MelonLoader.MelonLogger, MelonLoader.ModHandler", throwOnError: false); if ((object)type3 != null) { MethodInfo method4 = type3.GetMethod("Log", bindingAttr, null, new Type[2] { typeof(ConsoleColor), typeof(string) }, null); MethodInfo method5 = type3.GetMethod("Log", bindingAttr, null, new Type[1] { typeof(string) }, null); MethodInfo method6 = type3.GetMethod("LogWarning", bindingAttr, null, new Type[1] { typeof(string) }, null); MethodInfo method7 = type3.GetMethod("LogError", bindingAttr, null, new Type[1] { typeof(string) }, null); FastReflectionDelegate logDebug = method4.CreateFastDelegate(); FastReflectionDelegate logInfo = method5.CreateFastDelegate(); FastReflectionDelegate logWarning = method6.CreateFastDelegate(); FastReflectionDelegate logError = method7.CreateFastDelegate(); _logMethod = delegate(LogLevel level, string msg) { switch (level) { case LogLevel.Debug: logDebug(null, ConsoleColor.Gray, msg); break; case LogLevel.Info: logInfo(null, msg); break; case LogLevel.Warn: logWarning(null, msg); break; case LogLevel.Error: logError(null, msg); break; default: throw new ArgumentException("level"); } }; } } if (_logMethod != null) { return; } throw new Exception("Did not recognize any mod loader!"); } protected override void Log(LogLevel level, string message) { _logMethod(level, message); } public static int Convert(LogLevel level) { return level switch { LogLevel.Debug => 32, LogLevel.Info => 16, LogLevel.Warn => 4, LogLevel.Error => 2, _ => 0, }; } } public abstract class XuaLogger { private static XuaLogger _default; private static XuaLogger _common; private static XuaLogger _resourceRedirector; public static XuaLogger AutoTranslator { get { if (_default == null) { _default = CreateLogger("XUnity.AutoTranslator"); } return _default; } set { _default = value ?? throw new ArgumentNullException("value"); } } public static XuaLogger Common { get { if (_common == null) { _common = CreateLogger("XUnity.Common"); } return _common; } set { _common = value ?? throw new ArgumentNullException("value"); } } public static XuaLogger ResourceRedirector { get { if (_resourceRedirector == null) { _resourceRedirector = CreateLogger("XUnity.ResourceRedirector"); } return _resourceRedirector; } set { _resourceRedirector = value ?? throw new ArgumentNullException("value"); } } public string Source { get; set; } internal static XuaLogger CreateLogger(string source) { try { return new ModLoaderSpecificLogger(source); } catch (Exception) { return new ConsoleLogger(source); } } public XuaLogger(string source) { Source = source; } public void Error(Exception e, string message) { Log(LogLevel.Error, message + Environment.NewLine + e); } public void Error(string message) { Log(LogLevel.Error, message); } public void Warn(Exception e, string message) { Log(LogLevel.Warn, message + Environment.NewLine + e); } public void Warn(string message) { Log(LogLevel.Warn, message); } public void Info(Exception e, string message) { Log(LogLevel.Info, message + Environment.NewLine + e); } public void Info(string message) { Log(LogLevel.Info, message); } public void Debug(Exception e, string message) { Log(LogLevel.Debug, message + Environment.NewLine + e); } public void Debug(string message) { Log(LogLevel.Debug, message); } protected abstract void Log(LogLevel level, string message); protected string GetDefaultPrefix(LogLevel level) { return level switch { LogLevel.Debug => "[DEBUG][" + Source + "]: ", LogLevel.Info => "[INFO][" + Source + "]: ", LogLevel.Warn => "[WARN][" + Source + "]: ", LogLevel.Error => "[ERROR][" + Source + "]: ", _ => "[UNKNOW][" + Source + "]: ", }; } } } namespace XUnity.Common.Harmony { public static class AccessToolsShim { private static readonly BindingFlags All; private static readonly Func<Type, string, Type[], Type[], MethodInfo> AccessTools_Method; private static readonly Func<Type, string, PropertyInfo> AccessTools_Property; static AccessToolsShim() { All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = ClrTypes.AccessTools.GetMethod("Method", All, null, new Type[4] { typeof(Type), typeof(string), typeof(Type[]), typeof(Type[]) }, null); MethodInfo? method2 = ClrTypes.AccessTools.GetMethod("Property", All, null, new Type[2] { typeof(Type), typeof(string) }, null); AccessTools_Method = (Func<Type, string, Type[], Type[], MethodInfo>)ExpressionHelper.CreateTypedFastInvoke(method); AccessTools_Property = (Func<Type, string, PropertyInfo>)ExpressionHelper.CreateTypedFastInvoke(method2); } public static MethodInfo Method(Type type, string name, params Type[] parameters) { return AccessTools_Method(type, name, parameters, null); } public static PropertyInfo Property(Type type, string name) { return AccessTools_Property(type, name); } } } namespace XUnity.Common.Extensions { public static class ExceptionExtensions { public static TException FirstInnerExceptionOfType<TException>(this Exception e) where TException : Exception { for (Exception ex = e; ex != null; ex = ex.InnerException) { if (ex is TException) { return (TException)ex; } } return null; } } public static class ObjectExtensions { public static Type GetUnityType(this object obj) { return obj.GetType(); } public static bool TryCastTo<TObject>(this object obj, out TObject castedObject) { if (obj is TObject val) { castedObject = val; return true; } castedObject = default(TObject); return false; } } public static class StreamExtensions { public static byte[] ReadFully(this Stream stream, int initialLength) { if (initialLength < 1) { initialLength = 32768; } byte[] array = new byte[initialLength]; int num = 0; int num2; while ((num2 = stream.Read(array, num, array.Length - num)) > 0) { num += num2; if (num == array.Length) { int num3 = stream.ReadByte(); if (num3 == -1) { return array; } byte[] array2 = new byte[array.Length * 2]; Array.Copy(array, array2, array.Length); array2[num] = (byte)num3; array = array2; num++; } } byte[] array3 = new byte[num]; Array.Copy(array, array3, num); return array3; } } public static class StringExtensions { private static readonly HashSet<char> InvalidFileNameChars = new HashSet<char>(Path.GetInvalidFileNameChars()); public static string UseCorrectDirectorySeparators(this string path) { if (Path.DirectorySeparatorChar == '\\') { return path.Replace('/', Path.DirectorySeparatorChar); } if (Path.DirectorySeparatorChar == '/') { return path.Replace('\\', Path.DirectorySeparatorChar); } return path; } public static bool IsNullOrWhiteSpace(this string value) { if (value == null) { return true; } for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { return false; } } return true; } public static string MakeRelativePath(this string fullOrRelativePath, string basePath) { StringBuilder stringBuilder = new StringBuilder(); int i = 0; bool flag = false; string[] array = basePath.Split(':', '\\', '/'); List<string> list = fullOrRelativePath.Split(':', '\\', '/').ToList(); if (array.Length == 0 || list.Count <= 0 || array[0] != list[0]) { flag = true; } bool flag2 = false; for (int j = 0; j < list.Count; j++) { if (list[j] == "..") { if (flag2) { int num = j - 1; if (num >= 0) { list.RemoveAt(j); list.RemoveAt(num); j -= 2; } } } else { flag2 = true; } } if (!flag) { for (i = 1; i < array.Length && !(array[i] != list[i]); i++) { } for (int k = 0; k < array.Length - i; k++) { char directorySeparatorChar = Path.DirectorySeparatorChar; stringBuilder.Append(".." + directorySeparatorChar); } } for (int l = i; l < list.Count - 1; l++) { string value = list[l]; stringBuilder.Append(value).Append(Path.DirectorySeparatorChar); } string value2 = list[^1]; stringBuilder.Append(value2); return stringBuilder.ToString(); } public static string SanitizeForFileSystem(this string path) { StringBuilder stringBuilder = new StringBuilder(path.Length); foreach (char c in path) { if (!InvalidFileNameChars.Contains(c)) { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static string SplitToLines(this string text, int maxStringLength, params char[] splitOnCharacters) { StringBuilder stringBuilder = new StringBuilder(); int num; for (int i = 0; text.Length > i; i += num) { if (i != 0) { stringBuilder.Append('\n'); } num = ((i + maxStringLength <= text.Length) ? text.Substring(i, maxStringLength).LastIndexOfAny(splitOnCharacters) : (text.Length - i)); num = ((num == -1) ? maxStringLength : num); stringBuilder.Append(text.Substring(i, num).Trim()); } return stringBuilder.ToString(); } public static bool StartsWithStrict(this string str, string prefix) { int num = Math.Min(str.Length, prefix.Length); if (num < prefix.Length) { return false; } for (int i = 0; i < num; i++) { if (str[i] != prefix[i]) { return false; } } return true; } public static string GetBetween(this string strSource, string strStart, string strEnd) { int num = strSource.IndexOf(strStart); if (num != -1) { num += strStart.Length; int num2 = strSource.IndexOf(strEnd, num); if (num2 > num) { return strSource.Substring(num, num2 - num); } } return string.Empty; } public static bool RemindsOf(this string that, string other) { if (!that.StartsWith(other) && !other.StartsWith(that) && !that.EndsWith(other)) { return other.EndsWith(that); } return true; } } } namespace XUnity.Common.Constants { public static class ClrTypes { public static readonly Type AccessTools = FindTypeStrict("Harmony.AccessTools, 0Harmony") ?? FindTypeStrict("HarmonyLib.AccessTools, 0Harmony") ?? FindTypeStrict("Harmony.AccessTools, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.AccessTools, MelonLoader.ModHandler"); public static readonly Type HarmonyMethod = FindTypeStrict("Harmony.HarmonyMethod, 0Harmony") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyMethod, MelonLoader.ModHandler") ?? FindTypeStrict("HarmonyLib.HarmonyMethod, MelonLoader.ModHandler"); public static readonly Type HarmonyInstance = FindTypeStrict("Harmony.HarmonyInstance, 0Harmony") ?? FindTypeStrict("Harmony.HarmonyInstance, MelonLoader.ModHandler"); public static readonly Type Harmony = FindTypeStrict("HarmonyLib.Harmony, 0Harmony") ?? FindTypeStrict("HarmonyLib.Harmony, MelonLoader.ModHandler"); public static readonly Type Hook = FindTypeStrict("MonoMod.RuntimeDetour.Hook, MonoMod.RuntimeDetour"); public static readonly Type Detour = FindTypeStrict("MonoMod.RuntimeDetour.Detour, MonoMod.RuntimeDetour"); public static readonly Type NativeDetour = FindTypeStrict("MonoMod.RuntimeDetour.NativeDetour, MonoMod.RuntimeDetour"); public static readonly Type DynamicMethodDefinition = FindTypeStrict("MonoMod.Utils.DynamicMethodDefinition, MonoMod.Utils"); public static readonly Type Imports = FindTypeStrict("MelonLoader.Imports, MelonLoader.ModHandler"); public static readonly Type MethodBase = FindType("System.Reflection.MethodBase"); public static readonly Type Task = FindType("System.Threading.Tasks.Task"); private static Type FindType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return type; } } catch { } } return null; } private static Type FindTypeStrict(string name) { return Type.GetType(name, throwOnError: false); } } public class TypeContainer { public Type ClrType { get; } public Type UnityType { get; } public TypeContainer(Type type) { UnityType = type; ClrType = type; } public bool IsAssignableFrom(Type unityType) { if ((object)UnityType != null) { return UnityType.IsAssignableFrom(unityType); } return false; } } public static class UnityFeatures { private static readonly BindingFlags All; public static bool SupportsMouseScrollDelta { get; } public static bool SupportsClipboard { get; } public static bool SupportsCustomYieldInstruction { get; } public static bool SupportsSceneManager { get; } public static bool SupportsWaitForSecondsRealtime { get; set; } static UnityFeatures() { All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; SupportsMouseScrollDelta = false; SupportsClipboard = false; SupportsCustomYieldInstruction = false; SupportsSceneManager = false; SupportsWaitForSecondsRealtime = false; try { SupportsClipboard = (object)UnityTypes.TextEditor?.ClrType.GetProperty("text")?.GetSetMethod() != null; } catch (Exception) { } try { SupportsCustomYieldInstruction = UnityTypes.CustomYieldInstruction != null; } catch (Exception) { } try { SupportsSceneManager = UnityTypes.Scene != null && UnityTypes.SceneManager != null && (object)UnityTypes.SceneManager.ClrType.GetMethod("add_sceneLoaded", All) != null; } catch (Exception) { } try { SupportsMouseScrollDelta = (object)UnityTypes.Input?.ClrType.GetProperty("mouseScrollDelta") != null; } catch (Exception) { } try { SupportsWaitForSecondsRealtime = UnityTypes.WaitForSecondsRealtime != null; } catch (Exception) { } } } public static class UnityTypes { public static class TMP_Settings_Properties { public static CachedProperty Version = TMP_Settings?.ClrType.CachedProperty("version"); public static CachedProperty FallbackFontAssets = TMP_Settings?.ClrType.CachedProperty("fallbackFontAssets"); } public static class TMP_FontAsset_Properties { public static CachedProperty Version = TMP_FontAsset?.ClrType.CachedProperty("version"); } public static class AdvScenarioData_Properties { public static CachedProperty ScenarioLabels = AdvScenarioData?.ClrType.CachedProperty("ScenarioLabels"); } public static class UguiNovelText_Properties { public static CachedProperty TextGenerator = UguiNovelText?.ClrType.CachedProperty("TextGenerator"); } public static class UguiNovelText_Methods { public static CachedMethod SetAllDirty = UguiNovelText?.ClrType.CachedMethod("SetAllDirty"); } public static class UguiNovelTextGenerator_Methods { public static CachedMethod Refresh = UguiNovelTextGenerator?.ClrType.CachedMethod("Refresh"); } public static class AdvUguiMessageWindow_Properties { public static CachedProperty Text = AdvUguiMessageWindow?.ClrType.CachedProperty("Text"); public static CachedProperty Engine = AdvUguiMessageWindow?.ClrType.CachedProperty("Engine"); } public static class AdvUiMessageWindow_Fields { public static CachedField text = AdvUiMessageWindow?.ClrType.CachedField("text"); public static CachedField nameText = AdvUiMessageWindow?.ClrType.CachedField("nameText"); } public static class AdvUguiMessageWindow_Fields { public static FieldInfo text = AdvUguiMessageWindow?.ClrType.GetField("text", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); public static FieldInfo nameText = AdvUguiMessageWindow?.ClrType.GetField("nameText", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); public static FieldInfo engine = AdvUguiMessageWindow?.ClrType.GetField("engine", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } public static class AdvEngine_Properties { public static CachedProperty Page = AdvEngine?.ClrType.CachedProperty("Page"); } public static class AdvPage_Methods { public static CachedMethod RemakeTextData = AdvPage?.ClrType.CachedMethod("RemakeTextData"); public static CachedMethod RemakeText = AdvPage?.ClrType.CachedMethod("RemakeText"); public static CachedMethod ChangeMessageWindowText = AdvPage?.ClrType.CachedMethod("ChangeMessageWindowText", typeof(string), typeof(string), typeof(string), typeof(string)); } public static class UILabel_Properties { public static CachedProperty MultiLine = UILabel?.ClrType.CachedProperty("multiLine"); public static CachedProperty OverflowMethod = UILabel?.ClrType.CachedProperty("overflowMethod"); public static CachedProperty SpacingX = UILabel?.ClrType.CachedProperty("spacingX"); public static CachedProperty UseFloatSpacing = UILabel?.ClrType.CachedProperty("useFloatSpacing"); } public static class Text_Properties { public static CachedProperty Font = Text?.ClrType.CachedProperty("font"); public static CachedProperty FontSize = Text?.ClrType.CachedProperty("fontSize"); public static CachedProperty HorizontalOverflow = Text?.ClrType.CachedProperty("horizontalOverflow"); public static CachedProperty VerticalOverflow = Text?.ClrType.CachedProperty("verticalOverflow"); public static CachedProperty LineSpacing = Text?.ClrType.CachedProperty("lineSpacing"); public static CachedProperty ResizeTextForBestFit = Text?.ClrType.CachedProperty("resizeTextForBestFit"); public static CachedProperty ResizeTextMinSize = Text?.ClrType.CachedProperty("resizeTextMinSize"); public static CachedProperty ResizeTextMaxSize = Text?.ClrType.CachedProperty("resizeTextMaxSize"); } public static class InputField_Properties { public static CachedProperty Placeholder = InputField?.ClrType.CachedProperty("placeholder"); } public static class TMP_InputField_Properties { public static CachedProperty Placeholder = TMP_InputField?.ClrType.CachedProperty("placeholder"); } public static class Font_Properties { public static CachedProperty FontSize = Font?.ClrType.CachedProperty("fontSize"); } public static class AssetBundle_Methods { public static CachedMethod LoadAll = AssetBundle?.ClrType.CachedMethod("LoadAll", typeof(Type)); public static CachedMethod LoadAllAssets = AssetBundle?.ClrType.CachedMethod("LoadAllAssets", typeof(Type)); public static CachedMethod LoadFromFile = AssetBundle?.ClrType.CachedMethod("LoadFromFile", typeof(string)); public static CachedMethod CreateFromFile = AssetBundle?.ClrType.CachedMethod("CreateFromFile", typeof(string)); } public static class TextExpansion_Methods { public static CachedMethod SetMessageType = TextExpansion?.ClrType.CachedMethod("SetMessageType"); public static CachedMethod SkipTypeWriter = TextExpansion?.ClrType.CachedMethod("SkipTypeWriter"); } public static class GameObject_Methods { } public static class TextMesh_Methods { } public static class Text_Methods { } public static class InputField_Methods { } public static class TMP_Text_Methods { } public static class TMP_InputField_Methods { } public static class TextMeshPro_Methods { } public static class TextMeshProUGUI_Methods { } public static class UILabel_Methods { } public static class UIRect_Methods { } public static class SceneManager_Methods { public static readonly Action<UnityAction<Scene, LoadSceneMode>> add_sceneLoaded = (Action<UnityAction<Scene, LoadSceneMode>>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(SceneManager).GetMethod("add_sceneLoaded", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(UnityAction<Scene, LoadSceneMode>) }, null)); } public static class Texture2D_Methods { public static readonly Func<Texture2D, byte[], bool> LoadImage = (Func<Texture2D, byte[], bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(byte[]) }, null)); public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(typeof(Texture2D).GetMethod("EncodeToPNG", BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null)); } public static class ImageConversion_Methods { public static readonly Func<Texture2D, byte[], bool, bool> LoadImage = (Func<Texture2D, byte[], bool, bool>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null)); public static readonly Func<Texture2D, byte[]> EncodeToPNG = (Func<Texture2D, byte[]>)ExpressionHelper.CreateTypedFastInvokeUnchecked(ImageConversion?.ClrType.GetMethod("EncodeToPNG", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Texture2D) }, null)); } public static readonly TypeContainer UILabel = FindType("UILabel"); public static readonly TypeContainer UIWidget = FindType("UIWidget"); public static readonly TypeContainer UIAtlas = FindType("UIAtlas"); public static readonly TypeContainer UISprite = FindType("UISprite"); public static readonly TypeContainer UITexture = FindType("UITexture"); public static readonly TypeContainer UI2DSprite = FindType("UI2DSprite"); public static readonly TypeContainer UIFont = FindType("UIFont"); public static readonly TypeContainer UIPanel = FindType("UIPanel"); public static readonly TypeContainer UIRect = FindType("UIRect"); public static readonly TypeContainer UIInput = FindType("UIInput"); public static readonly TypeContainer TextField = FindType("FairyGUI.TextField"); public static readonly TypeContainer TMP_InputField = FindType("TMPro.TMP_InputField"); public static readonly TypeContainer TMP_Text = FindType("TMPro.TMP_Text"); public static readonly TypeContainer TextMeshProUGUI = FindType("TMPro.TextMeshProUGUI"); public static readonly TypeContainer TextMeshPro = FindType("TMPro.TextMeshPro"); public static readonly TypeContainer TMP_FontAsset = FindType("TMPro.TMP_FontAsset"); public static readonly TypeContainer TMP_Settings = FindType("TMPro.TMP_Settings"); public static readonly TypeContainer GameObject = FindType("UnityEngine.GameObject"); public static readonly TypeContainer Transform = FindType("UnityEngine.Transform"); public static readonly TypeContainer TextMesh = FindType("UnityEngine.TextMesh"); public static readonly TypeContainer Text = FindType("UnityEngine.UI.Text"); public static readonly TypeContainer Image = FindType("UnityEngine.UI.Image"); public static readonly TypeContainer RawImage = FindType("UnityEngine.UI.RawImage"); public static readonly TypeContainer MaskableGraphic = FindType("UnityEngine.UI.MaskableGraphic"); public static readonly TypeContainer Graphic = FindType("UnityEngine.UI.Graphic"); public static readonly TypeContainer GUIContent = FindType("UnityEngine.GUIContent"); public static readonly TypeContainer WWW = FindType("UnityEngine.WWW"); public static readonly TypeContainer InputField = FindType("UnityEngine.UI.InputField"); public static readonly TypeContainer GUI = FindType("UnityEngine.GUI"); public static readonly TypeContainer GUI_ToolbarButtonSize = FindType("UnityEngine.GUI+ToolbarButtonSize"); public static readonly TypeContainer GUIStyle = FindType("UnityEngine.GUIStyle"); public static readonly TypeContainer ImageConversion = FindType("UnityEngine.ImageConversion"); public static readonly TypeContainer Texture2D = FindType("UnityEngine.Texture2D"); public static readonly TypeContainer Texture = FindType("UnityEngine.Texture"); public static readonly TypeContainer SpriteRenderer = FindType("UnityEngine.SpriteRenderer"); public static readonly TypeContainer Sprite = FindType("UnityEngine.Sprite"); public static readonly TypeContainer Object = FindType("UnityEngine.Object"); public static readonly TypeContainer TextEditor = FindType("UnityEngine.TextEditor"); public static readonly TypeContainer CustomYieldInstruction = FindType("UnityEngine.CustomYieldInstruction"); public static readonly TypeContainer SceneManager = FindType("UnityEngine.SceneManagement.SceneManager"); public static readonly TypeContainer Scene = FindType("UnityEngine.SceneManagement.Scene"); public static readonly TypeContainer UnityEventBase = FindType("UnityEngine.Events.UnityEventBase"); public static readonly TypeContainer BaseInvokableCall = FindType("UnityEngine.Events.BaseInvokableCall"); public static readonly TypeContainer Font = FindType("UnityEngine.Font"); public static readonly TypeContainer WaitForSecondsRealtime = FindType("UnityEngine.WaitForSecondsRealtime"); public static readonly TypeContainer Input = FindType("UnityEngine.Input"); public static readonly TypeContainer AssetBundleCreateRequest = FindType("UnityEngine.AssetBundleCreateRequest"); public static readonly TypeContainer AssetBundle = FindType("UnityEngine.AssetBundle"); public static readonly TypeContainer AssetBundleRequest = FindType("UnityEngine.AssetBundleRequest"); public static readonly TypeContainer Resources = FindType("UnityEngine.Resources"); public static readonly TypeContainer AsyncOperation = FindType("UnityEngine.AsyncOperation"); public static readonly TypeContainer TextAsset = FindType("UnityEngine.TextAsset"); public static readonly Type HorizontalWrapMode = FindClrType("UnityEngine.HorizontalWrapMode"); public static readonly Type TextOverflowModes = FindClrType("TMPro.TextOverflowModes"); public static readonly Type TextAlignmentOptions = FindClrType("TMPro.TextAlignmentOptions"); public static readonly Type VerticalWrapMode = FindClrType("UnityEngine.VerticalWrapMode"); public static readonly TypeContainer TextExpansion = FindType("UnityEngine.UI.TextExpansion"); public static readonly TypeContainer Typewriter = FindType("Typewriter"); public static readonly TypeContainer UguiNovelText = FindType("Utage.UguiNovelText"); public static readonly TypeContainer UguiNovelTextGenerator = FindType("Utage.UguiNovelTextGenerator"); public static readonly TypeContainer AdvEngine = FindType("Utage.AdvEngine"); public static readonly TypeContainer AdvPage = FindType("Utage.AdvPage"); public static readonly TypeContainer TextData = FindType("Utage.TextData"); public static readonly TypeContainer AdvUguiMessageWindow = FindType("Utage.AdvUguiMessageWindow") ?? FindType("AdvUguiMessageWindow"); public static readonly TypeContainer AdvUiMessageWindow = FindType("AdvUiMessageWindow"); public static readonly TypeContainer AdvDataManager = FindType("Utage.AdvDataManager"); public static readonly TypeContainer AdvScenarioData = FindType("Utage.AdvScenarioData"); public static readonly TypeContainer AdvScenarioLabelData = FindType("Utage.AdvScenarioLabelData"); public static readonly TypeContainer DicingTextures = FindType("Utage.DicingTextures"); public static readonly TypeContainer DicingImage = FindType("Utage.DicingImage"); public static readonly TypeContainer TextArea2D = FindType("Utage.TextArea2D"); public static readonly TypeContainer CubismRenderer = FindType("Live2D.Cubism.Rendering.CubismRenderer"); public static readonly TypeContainer TextWindow = FindType("Assets.System.Text.TextWindow"); private static Type FindClrType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return type; } } catch { } } return null; } private static TypeContainer FindType(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(name, throwOnError: false); if ((object)type != null) { return new TypeContainer(type); } } catch { } } return null; } } }
BepInEx/plugins/RussianTranslateTerminal.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("TerminalTranslator")] [assembly: AssemblyDescription("该文件由B站用户吹到江心的孤雪制作并编译, 个人链接为https://space.bilibili.com/21754758, 未经本人允许, 请勿擅自改造分发, 造成任何后果及危害, 本人概不负责. 本人及本制作方享有最终解释权。")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("TerminalTranslator")] [assembly: AssemblyCopyright("Copyright © B站吹到江心的孤雪 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("7286f300-1e32-456a-8efc-5d28af5344d6")] [assembly: AssemblyFileVersion("0.9.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.9.0.0")] namespace RussianTranslateTerminal { [BepInPlugin("snowflake.plugin.russiantranslateterminal", "RussianTranslateTerminal", "1.0.0")] public class RussianTranslateTerminal : BaseUnityPlugin { private const string PLUGIN_GUID = "snowflake.plugin.russiantranslateterminal"; private const string PLUGIN_NAME = "RussianTranslateTerminal"; private const string PLUGIN_VERSION = "1.0.0"; private readonly Harmony harmony = new Harmony("snowflake.plugin.russiantranslateterminal"); private void Awake() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin snowflake.plugin.russiantranslateterminal (RussianTranslateTerminal) is loaded!"); PatchHarmony(); } private void PatchHarmony() { try { harmony.PatchAll(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error applying Harmony patches: " + ex.Message)); } } } } namespace TerminalTranslator { internal class RussianTranslateTerminal { private bool firstUse = true; public string translate(ref string modifiedDisplayText, ref TerminalNode node) { string text = node.displayText.ToString(); if (firstUse & (((Object)node).name == "OtherCommands")) { modifiedDisplayText = modifiedDisplayText.Replace(".\n\n\n", ".\n\n>TRANSLATE\nИнформация о переводе.\n\n"); } string result; if (text.Contains("[translate]")) { credits(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[currentDay]")) { translateWelcome(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[numberOfItemsOnRoute]")) { translateMenu(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[planetTime]")) { translateCommandMoons(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[unlockablesSelectionList]")) { translateCommandStore(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[currentScannedEnemiesList]")) { translateCommandBestiary(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[storedUnlockablesList]")) { translateCommandStorage(ref modifiedDisplayText); result = modifiedDisplayText; } else if (text.Contains("[currentUnlockedLogsList]")) { translateCommandSigurd(ref modifiedDisplayText); result = modifiedDisplayText; } else { translateCommandOther(ref modifiedDisplayText); translateMisc(ref modifiedDisplayText); translateDetailStore(ref modifiedDisplayText); if (modifiedDisplayText.Length > 180) { if (!translateDetailMoons(ref modifiedDisplayText)) { return modifiedDisplayText; } if (!translateDetailBestiary(ref modifiedDisplayText)) { return modifiedDisplayText; } if (!translateDetailSigurd(ref modifiedDisplayText)) { return modifiedDisplayText; } } result = modifiedDisplayText; } return result; } public void credits(ref string raw) { raw = "\n\n\nДобро пожаловать в раздел информации о переводе.\nТут можно узнать об авторах и помощниках проекта.\nВ будущем данный раздел будет пополняться.\n____________________________\n\n* Автор перевода: Hayrizan\n\n* Помощь с консолью: incredibleIdean\n* Корректировщик перевода: kon4arich\n\n\n"; } public void translateWelcome(ref string raw) { raw = raw.Replace("Welcome to the FORTUNE-9 OS", "Добро пожаловать в FORTUNE-9 ОС").Replace("Courtesy of the Company", "Любезно предоставлено Компанией").Replace("Happy Monday.", "Счастливого понедельника!") .Replace("Happy Tuesday.", "Счастливого вторника!") .Replace("Happy Wednesday.", "Счастливой среды!") .Replace("Happy Thursday.", "Счастливого четверга!") .Replace("Happy Friday.", "Счастливой пятницы!") .Replace("Happy Saturday.", "Счастливой субботы!") .Replace("Happy Sunday.", "Счастливого воскресенья!") .Replace("Type \"Help\" for a list of commands.", "Введите \"HELP\" для вывода списка команд."); } public void translateMenu(ref string raw) { raw = raw.Replace("To see the list of moons the autopilot can route to.", "Посмотреть список лун, на которые можно задать курс для автопилота.").Replace("To see the company store's selection of useful items.", "Посмотреть подборку полезных товаров в фирменном магазине.").Replace("To see the list of wildlife on record.", "Посмотреть список записей о существах.") .Replace("To access objects placed into storage.", "Получить доступ к объектам, помещенным на склад.") .Replace("To see the list of other commands", "Вывести список остальных команд.".Replace("purchased items on route.", "шт. купленного товара уже в пути.")); } public void translateCommandMoons(ref string raw) { raw = raw.Replace("Welcome to the exomoons catalogue.", "Добро пожаловать в каталог экзолун.").Replace("To route the autopilot to a moon, use the word ROUTE.", "Чтобы задать курс для автопилота на луну, используйте \"ROUTE\".").Replace("To learn about any moon, use the word INFO.", "Чтобы узнать побольше информации о какой-либо луне, используйте \"INFO\".") .Replace("Buying at", "Покупает за") .Replace("Eclipsed", "затмение") .Replace("Flooded", "наводнение") .Replace("Stormy", "гроза") .Replace("Foggy", "туман") .Replace("Rainy", "дождь"); } public void translateCommandStore(ref string raw) { raw = raw.Replace("Welcome to the Company store.", "Добро пожаловать в магазин Компании.").Replace("Use words BUY and INFO on any item.", "Используйте \"BUY\" и \"INFO\" для любого товара.").Replace("Order tools in bulk by typing a number.", "Закажите инструменты оптом, указав количество.") .Replace("Price:", "цена:") .Replace("* Walkie-talkie", "* Рация (walkie-talkie)") .Replace("* Spray paint", "* Баллончик с краской (spray paint)") .Replace("* Flashlight", "* Фонарик (flashlight)") .Replace("* Shovel", "* Лопата (shovel)") .Replace("* Lockpicker", "* Автоотмычка (lockpicker)") .Replace("* Pro-flashlight", "* Улучш. фонарик (pro-flashlight)") .Replace("* Stun grenade", "* Светошум. граната (stun grenade)") .Replace("* Boombox", "* Бумбокс (boombox)") .Replace("* TZP-Inhalant", "* Ингалятор (tzp-inhalant)") .Replace("* Zap gun", "* Электрошокер (zap gun)") .Replace("* Jetpack", "* Реакт. ранец (jetpack)") .Replace("* Extension ladder", "* Выдв. лестница (extension ladder)") .Replace("* Radar-booster", "* Радарный усилитель (radar-booster)") .Replace("SHIP UPGRADES:", "УЛУЧШЕНИЯ ДЛЯ КОРАБЛЯ:") .Replace("* Loud horn", "* Громкий горн (loud horn)") .Replace("Goldfish", "Золотая рыбка (goldfish)") .Replace("Plushie pajama man", "Плюшевый человек-пижама (plushie pajama man)") .Replace("* Teleporter", "* Телепорт (teleporter)") .Replace("* Signal Translator", "* Транслятор сигналов (signal translator)") .Replace("* Inverse Teleporter", "* Обратный телепорт (inverse teleporter)") .Replace("The selection of ship decor rotates per-quota. Be sure to check back next week:", "Ассортимент декора для корабля обновляется каждую новую квоту. Обязательно проверьте на следующей неделе!") .Replace("Romantic table", "Романтический стол (romantic table)") .Replace("Toilet", "Унитаз (toilet)") .Replace("Shower", "Душевая кабина (shower)") .Replace("Table", "Стол (table)") .Replace("Record player", "Проигрыватель (record player)") .Replace("Cozy lights", "Гирлянда (cozy lights)") .Replace("Pajama suit", "Пижамный костюм (pajama suit)") .Replace("Green suit", "Зеленый костюм (green suit)") .Replace("Hazard suit", "Защитный костюм (hazard suit)") .Replace("Television", "Телевизор (television)") .Replace("Jack-o-Lantern", "Фонарь из тыквы (jack-o-lantern)"); } public void translateCommandBestiary(ref string raw) { raw = raw.Replace("To access a creature file, type \"INFO\" after its name.", "Чтобы получить доступ к файлу о существе, используйте \"INFO\".").Replace("No data collected on wildlife. Scans are required.", "Нет никаких данных о существах. Требуется сканирование.").Replace("NEW", "НОВОЕ") .Replace("Hygroderes", "Гигродеры (hygroderes)") .Replace("Snare fleas", "Блохоловки (snare fleas)") .Replace("Bunker spiders", "Бункерные пауки (bunker spiders)") .Replace("Hoarding bugs", "Жуки-воровки (hoarding bugs)") .Replace("Thumpers", "Топтуны (thumpers)") .Replace("Coil-heads", "Пружиноголовые (coil-heads)") .Replace("Spore lizards", "Споровые ящеры (spore lizards)") .Replace("Brackens", "Папоротники (brackens)") .Replace("Jesters", "Шуты (jesters)") .Replace("Manticoils", "Мантикойлы (manticoils)") .Replace("Roaming locusts", "Бродячая саранча (roaming locusts)") .Replace("Circuit bees", "Цепные пчелы (circuit bees)") .Replace("Baboon hawks", "Ястребы-бабуины (baboon hawks)") .Replace("Eyeless dogs", "Безглазые собаки (eyeless dogs)") .Replace("Forest keepers", "Хранители леса (forest keepers)") .Replace("Earth leviathans", "Земляные Левиафаны (earth leviathans)"); } public void translateCommandStorage(ref string raw) { raw = raw.Replace("While moving furniture with [B], you can press [X] to send it to storage. You can call it back from storage here.", "При перемещении объекта с помощью [B], вы можете нажать [X], чтобы отправить его на склад. Здесь вы можете отозвать его обратно.").Replace("These are the items in storage:", "Объекты на складе:").Replace("Order tools in bulk by typing a number.", "Закажите инструменты оптом, указав количество.") .Replace("[No items stored. While moving an object with B, press X to store it.]", "На складе ничего нет. При перемещении объекта с помощью [B], нажмите [X], чтобы складировать его.") .Replace("Loud horn\n", "Громкий горн (loud horn)\n") .Replace("Inverse Teleporter\n", "Обратный телепорт (inverse teleporter)\n") .Replace("Teleporter\n", "Телепорт (teleporter)\n"); translateCommandStore(ref raw); } public void translateCommandOther(ref string raw) { raw = raw.Replace("Other commands:", "Остальные команды:").Replace("To toggle on AND off the main monitor's map cam", "Переключение изображения с главного монитора.").Replace("[Player name]", "[имя игрока]") .Replace("To switch view to a player on the main monitor", "Выбрать игрока для наблюдения на главном мониторе (без аргумента — переключиться на следующего).") .Replace("[Radar booster name]", "[название радарного усилителя]") .Replace("[message]", "[сообщение]") .Replace("To transmit a message with the signal translator", "Передать сообщение через транслятор сигналов.") .Replace("To make a radar booster play a noise.", "Заставить радарный усилитель издать звук.") .Replace("To scan for the number of items left on the current planet.", "Просканировать оставшийся лом на текущей планете."); } public void translateCommandSigurd(ref string raw) { raw = raw.Replace("SIGURD'S LOG ENTRIES", "ЗАПИСИ ИЗ ЖУРНАЛА СИГУРДА").Replace("NEW", "НОВОЕ").Replace("To read a log, use keyword \"VIEW\" before its name.", "Чтобы прочитать запись, используйте \"VIEW\".") .Replace("First Log - Aug 22", "Первая запись - 22 авг. (first log)") .Replace("Smells here! - Aug 24", "Здесь воняет! - 24 авг. (smells here!)") .Replace("Swing of things - Aug 27", "Курс дела - 27 авг. (swing of things)") .Replace("Golden planet - Aug ??", "Золотая планета - ?? авг. (golden planet)") .Replace("Shady - Aug 31", "Прикрытие - 31 авг. (shady)") .Replace("Sound behind the wall - Sep 4", "Звук за стеной - 4 сент. (sound behind the wall)") .Replace("Goodbye - Sep 7", "Прощай - 7 сент. (goodbye)") .Replace("Screams - Sep 13", "Крики - 13 сент. (screams)") .Replace("Idea - Sep 19", "Идея - 19 сент. (idea)") .Replace("Nonsense - Sep 27", "Бред - 27 сент. (nonsense)") .Replace("Hiding - Sep 30", "Сокрытие - 30 сент. (hiding)") .Replace("Desmond - Oct 15", "Десмонд - 15 окт. (desmond)"); } public bool translateDetailMoons(ref string raw) { string text = raw; raw = raw.Replace("Go here to drop off any valuable scrap you've collected while on the job. The rate of return updates hourly and fluctuates over the course of several days.", "Летите сюда, чтобы сдать весь ценный лом, который вы собрали за время работы. Норма прибыли обновляется каждый час и меняется в течение нескольких дней.").Replace("CONDITIONS: Arid. Low habitability, worsened by industrial artifacts.", "УСЛОВИЯ: Засуха. Низкая пригодность для жизни, усугубленная промышленными артефактами.").Replace("HISTORY: Not discovered for quite some time due to its close orbit around gas giant Big Grin. However it appears to have been used in secret.", "ИСТОРИЯ: Некоторое время оставалась незамеченной из-за своей близкой орбиты вокруг газового гиганта Big Grin. Однако, судя по всему, кем-то использовалась тайно.") .Replace("FAUNA: Unknown", "ФАУНА: Неизвестно.") .Replace("CONDITIONS: Arid. Low habitability, worsened by industrial artifacts.", "УСЛОВИЯ: Засуха. Низкая пригодность для жизни, усугубленная промышленными артефактами.") .Replace("HISTORY: Not discovered for quite some time due to its close orbit around gas giant Big Grin. However it appears to have been used in secret.", "ИСТОРИЯ: Некоторое время оставалось незамеченной из-за своей близкой орбиты вокруг газового гиганта Big Grin. Однако, судя по всему, использовалась тайно.") .Replace("CONDITIONS: Similar to its twin moon, 41-Experimentation, featuring far more jagged and weathered terrain.", "УСЛОВИЯ: Похожая на свою луну-близнец 41-Experimentation, имеет гораздо более неровную и выветренную местность.") .Replace("HISTORY: 220-Assurance is far younger than its counterpart. Discovered not long before 41-Experimentation.", "ИСТОРИЯ: 220-Assurance гораздо младше своего двойника. Открыта незадолго до 41-Experimentation.") .Replace("CONDITIONS: Humid.", "УСЛОВИЯ: Влажность.") .Replace("HISTORY: Vow appears to have been inhabited by several colonies across its continents, but there is now no sign of life, and they have become a mystery.", "ИСТОРИЯ: По всей видимости, Vow была населена несколькими колониями на разных континентах, но сейчас нет никаких признаков жизни, что это стало загадкой.") .Replace("FAUNA: Diverse, teeming with plant-life", "ФАУНА: Разнообразие с обилием растительности.") .Replace("CONDITIONS: Believed to have splintered off from its cousin Assurance, Offense features similar jagged and dry conditions but differs in its ecosystem.", "УСЛОВИЯ: Считающаяся отколотой от своей кузины Assurance, Offense имеет такие же неровные и засушливые условия, но отличается своей экосистемой.") .Replace("HISTORY: 21-Offense is categorized as an asteroid moon and seems to have not existed on its own for more than several hundred years. The industrial artifacts here have suffered damage; it's believed they were built long before 21-Offense was splintered off.", "ИСТОРИЯ: 21-Offense относится к категории астероидных лун и, похоже, не существовала сама по себе более нескольких сотен лет. Промышленные артефакты здесь повреждены; считается, что они были построены задолго до того, как 21-Offense откололась.") .Replace("FAUNA: A competitive and toughened ecosystem supports aggressive lifeforms. Travellers to 21-Offense should know it's not for the faint of heart.", "ФАУНА: Конкурентоспособная и ужесточенная экосистема поддерживает агрессивные формы жизни. Путешественникам на 21-Offense следует знать, что это место не для слабонервных.") .Replace("CONDITIONS: March undergoes constant drizzling weather. Its terrain is more expansive.", "УСЛОВИЯ: March подвергается постоянной моросящей погоде. Ее местность более обширна.") .Replace("HISTORY: This moon is overlooked due to its twin moon, Vow.", "ИСТОРИЯ: Эта луна часто скрывается за ее луной-близнецом Vow.") .Replace("CONDITIONS: Its planet orbits white dwarf star, making for inhospitable, cold conditions. Constant blizzards decrease visibility.", "УСЛОВИЯ: Ее планета вращается вокруг белого карлика, что подразумевает собой негостеприимные холодные условия. Постоянные метели снижают видимость.") .Replace("HISTORY: Several famous travelers went missing here, giving it some reputation. Their bodies are unlikely to be found due to the planet's conditions.", "ИСТОРИЯ: Здесь пропали без вести несколько знаменитых путешественников, что придало этой луне определенную репутацию. Их тела вряд ли удастся найти из-за условий на планете.") .Replace("FAUNA: It's highly unlikely for complex life to exist here.", "ФАУНА: Существование сложной жизни здесь очень маловероятно.") .Replace("CONDITIONS: A frozen, flat landscape.", "УСЛОВИЯ: Заледеневший плоский ландшафт.") .Replace("HISTORY: It looks like this moon was mined for resources. It's easy to get lost within the giant industrial complex. There are many entrances to it littered about the landscape.", "ИСТОРИЯ: Похоже, что на этой луне велась добыча ресурсов. Внутри гигантского промышленного комплекса легко заблудиться. Возможные входы в него размещены по всему ландшафту.") .Replace("FAUNA: Dangerous entities have been rumored to take residence in the vast network of tunnels.", "ФАУНА: По слухам, в сети туннелей поселились опасные существа."); return raw == text; } public void translateDetailStore(ref string raw) { raw = raw.Replace("Useful for keeping in touch! Hear other players when the wakie talkie is in your inventory. Must be in your hand and pressed down to transmit voice", "Полезно для поддержания связи! Имейте возможность слышать других игроков, когда рация находится в вашем инвентаре. Для того, чтобы сказать что-то по рации, необходимо достать ее и удерживать соответствующую кнопку").Replace("The most affordable light source. It's even waterproof", "Самый доступный источник света. Он даже водонепроницаемый").Replace("For self-defense", "Для самообороны") .Replace("Lock-pickers will unlock your limitless potential for efficiency on the job. Powered by proprietary AI software, they will get you access through any locked door", "Автоотмычки раскроют ваш безграничный потенциал эффективности в работе. Благодаря запатентованному программному обеспечению с ИИ они помогут открыть вам любую запертую дверь") .Replace("With an extra battery life and even brighter bulb, your colleagues can never leave you in the dark again", "С увеличенным временем автономной работы и еще более яркой лампочкой ваши коллеги больше никогда не оставят вас в темноте") .Replace("[This action was not compatible with this object.]", "[Данное действие несовместимо с этим объектом]") .Replace("These jamming tunes are great for a morale boost on your crew", "Эти заедающие в голове мелодии быстро поднимут боевой дух вашего экипажа") .Replace("This safe and legal medicine can be administered to see great benefits to your performance on the job! Your ability to move LONG distances while carrying HEFTY objects will be second to none! Warning: TZP gas may impact the brain with extended exposure. Follow instructions manual provided with the canister", "Этот безопасный и легальный препарат можно принять, чтобы значительно улучшить вашу работоспособность! Ваша способность перемещаться на БОЛЬШИЕ расстояния, неся с собой ТЯЖЕЛЫЕ предметы, будет просто непревзойденной! Предупреждение: при длительном использовании газ ингалятора может оказывать действие на мозг. Следуйте инструкции, прилагаемой к баллончику") .Replace("Don't forget to share", "Не забудьте поделиться") .Replace("The most specialized self-protective equipment, capable of sending upwards of 80,000 volts", "Самое специализированное средство самозащиты, способное подавать напряжение до 80,000 вольт") .Replace("To keep it targeted as long as possible, pull the gun side-to-side to counter the bend and fight against the pull of the electric beam. It can only stun for as long as you keep the current flowing", "Чтобы удерживать цель как можно дольше, виляйте оружием из стороны в сторону, чтобы оказывать сопротивление изгибу и бороться с притяжением электрического луча. Он оглушает только тогда, когда вы поддерживаете ток") .Replace("This device will get you around anywhere! Just use it responsibly", "Это устройство доставит вас куда угодно! Просто используйте его с умом") .Replace("The extension ladder can reach as high as nine meters! Use it to scale any cliff and reach for the stars! To save batteries the extension ladder automatically stores itself after 18 seconds", "Выдвижная лестница может достигать девяти метров в длину! Используйте ее, чтобы взобраться на любую скалу и дотянуться до звезд! Для экономии зарядки выдвижная лестница автоматически складывается через 18 секунд") .Replace("Radar boosters come with many uses", "Радарные усилители имеют множество применений") .Replace("Use the \"SWITCH\" command before the radar booster's name to view it on the main monitor. It must be activated", "Используйте \"SWITCH\" перед именем радарного усилителя, чтобы переключиться на него на главном мониторе. Он должен быть заранее активирован") .Replace("Use the \"PING\" command before the radar booster's name to play a special sound from the device", "Используйте \"PING\" перед именем радарного усилителя, чтобы устройство издало звук") .Replace("Used to communicate with any crew member from any distance, no walkie talkie required! The horn can be heard from anywhere. But what does it mean? That's up to you", "Используется для связи с членами экипажа на любом расстоянии без нужды в рации! Гудок горна слышен откуда угодно. Но что он будет означать? Это зависит от вас") .Replace("Press the button to activate the teleporter. It will teleport whoever is currently being monitored on the ship's radar. They will not be able to keep any of their held items through the teleport. It takes about ten seconds to recharge", "Нажмите кнопку, чтобы активировать телепорт. Он телепортирует того, кто в данный момент находится под наблюдением радарной камеры на корабле. Вы не сможете перенести ни один из предметов с помощью телепортации. Перезарядка занимает около 10 секунд") .Replace("The inverse teleporter is a modified teleporter which will teleport you to a random position outside the ship. All your items will be dropped at the teleporter before transport. The inverse teleporter can be used by everyone at once and has a 3.5 minute cooldown", "Обратный телепорт — это модифицированный телепорт, который перемещает вас в случайное место за пределами корабля. Все переносимые предметы будут выброшены перед телепортацией. Обратный телепорт может использоваться всеми одновременно, перезарядка занимает 3.5 минуты") .Replace("DISCLAIMER: The inverse teleporter can only transport you out, not in, and you may become trapped. The Company is not responsible for injury or replacement of heads and limbs induced by quantum entanglement and bad luck", "ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Обратный телепорт может перенести вас только куда-то, но не обратно, поэтому вы можете оказаться в ловушке. Компания не несет ответственности за травмы или обмен головами и конечностями, вызванные квантовой запутанностью и невезением"); } public bool translateDetailBestiary(ref string raw) { string text = raw; raw = raw.Replace("Thumpers\n\n", "Топтун (thumper)\n\n").Replace("Sigurd's danger level: 90%\n\n", "Уровень опасности по шкале Сигурда: 90%\n\n").Replace("Scientific name: Pistris-saevus", "Научное название: Pistris-saevus") .Replace("Halves, or Thumpers, are a highly aggressive, carnivorous species of the order Chondrichthyes. Their skeletons are cartilaginous, giving their bodies a stretchy and rubbery quality. Their name comes from the fact they must eat their bottom legs in order to escape the shell of their hatched egg; their bottom legs are hardly functional to begin with. Their arms, or front legs, are very strong, and they occasionally use them to stomp prey. They can reach great speeds in a straight line.", "Половинчатый, или топтун — очень агрессивный плотоядный вид отряда хрящевых. Их скелет состоит только из хрящей, что придает телу гибкость и эластичность. Название происходит от того факта, что им приходится съедать свои задние ноги, чтобы выбраться из скорлупы вылупившегося яйца; задние конечности с самого рождения почти не функционируют. Их руки (либо же передние ноги) очень сильные, поэтому с их помощью могут легко затоптать добычу. Набирают огромную скорость по прямой.") .Replace("They are relentless hunters, typically at the top of their food chain. Their main weaknesses are their intelligence and complete lack of hearing. If you come across a thumper, your best means of survival are leaving its line of sight, as it is slower around corners and can't easily track prey.", "Они беспощадные охотники, которые обычно находятся на вершине пищевой цепи. Главные слабости — неразвитый интеллект и полное отсутствие слуха. Если вы встретите топтуна, лучший способ выжить — покинуть его поле зрения, так как он медленно разворачивается и плохо выслеживает добычу.") .Replace("Due to the fast and volatile evolution of this species, some theorize that thumpers are one of the examples of an increased number of mutations causing higher levels of speciation in planets around the Thistle Nebula.", "Из-за быстрой и нестабильной эволюции этого вида некоторые считают, что топтун — один из примеров увеличенного числа мутаций, которые являются причиной более высоких уровней видообразования на планетах вблизи туманности Чертополох.") .Replace("HOARDING BUG", "Жук-воровка (hoarding bug)") .Replace("Sigurd's danger level: 0%\n\n", "Уровень опасности по шкале Сигурда: 0%\n\n") .Replace("Scientific name: Linepithema-crassus", "Научное название: Linepithema-crassus") .Replace("Hoarding bugs (of the order Hymenoptera) are large, social insects. While often found living alone, they have been found to share their nests with members of their own species. They measure a height of 3 feet on average, with bulbous bodies. The thinness of their fluid and blood and the material of their carapaces contributes to their low weight, making them capable of flight with their membranous wings. It also makes their bodies somewhat transparent.", "Жуки-воровки (из отряда перепончатокрылых) — крупные социальные насекомые. Хотя их часто можно встретить живущими в одиночестве, было обнаружено, что они могут делить свои гнезда с представителями своего вида. Средняя высота их выпуклого тела составляет чуть меньше 1 метра. Тонкость кровеносных сосудов и легкость структуры панциря способствуют их малому весу, что позволяет им летать с помощью перепончатых крыльев. Ко всему прочему, это делает их тела немного прозрачными.") .Replace("Hoarding bugs were given their name due to their territorial nature. Once they have chosen a place as their nest, they will seek to adorn it with any object they can find and will protect these objects as a part of the nest. Hoarding bugs are not so dangerous alone as they are in large hives. However, if left alone, hoarding bugs are surprisingly neutral and pose little danger. wWe love the stupid cuddle bugs.!! - tjhis has been a note from the indomitable Sigurd", "Свое название жуки-воровки получили из-за своего территориального характера. Выбрав место в качестве гнезда, они стараются украсить его любыми предметами, что смогут найти, и будут защищать их как часть гнезда. Жуки-воровки не так уж и опасны поодиночке, нежели в больших гнездах. Однако, если оставить их в покое, жуки-воровки на удивление нейтральны и не представляют особой опасности.\n\nмМы любим этих глупеньких жучков-обнимашек!!1 — прииписка от несокрушимого Сигурда") .Replace("HYGRODERE", "Гигродер (hygrodere)") .Replace("Sigurd's danger level: 0%, if you're faster than a snail!", "Уровень опасности по шкале Сигурда: 0%, если вы быстрее улитки!") .Replace("Scientific name: Hygrodere", "Научное название: Hygrodere") .Replace("A eukaryotic organism classified within the paraphyletic group Prostita. With the incredible speed of reproduction, these small organisms can multiply to millions. Hygrodere rarely split apart, instead choosing to form large, viscous masses which can take up large amounts of space and become a danger to deal with, requiring large tools or lures to relocate.", "Эукариотический организм, относящийся к парафилетической группе протистов. Благодаря невероятной скорости размножения, эти небольшие организмы могут преумножиться до миллионов. Гигродеры редко разделяются на части, вместо этого предпочитая формировать большие вязкие массы, которые могут занимать огромные пространства и представлять собой опасность, требующую больших инструментов или приманок для безопасного перемещения.") .Replace("Hygrodere are drawn to heat and oxygen and can detect it from seemingly anywhere. There's almost nothing organic they can't convert to their own body mass. Nothing has been found to poison them. Constantly replacing themselves, they can persist for hundreds of thousands of years. If you ever find yourself cornered, find a tall object to stand on top of; hygroderes have trouble climbing. they have great taste! cause I made a friend with one somehow,, and we think it was my music.", "Гигродеры придерживаются тепла и кислорода, и могут найти их источники где угодно. Не существует почти ничего органического, что они не могли бы преобразовать в собственную массу тела. На данный момент не обнаружено ничего, что могло бы их отравить. Постоянно заменяя себя, они могут просуществовать сотни тысяч лет. Если вы когда-нибудь окажетесь загнанными в угол, найдите высокий уступ, на который можно залезть; у гигродер проблемы с этим.\n\nу них отличный вкус! потому что я как-то смог подружиться с одним из них,, и нам кажется, что это все из-за моей музыки.") .Replace("COIL-HEADS", "Пружиноголовый (coil-head)") .Replace("Sigurd's danger level: 80%", "Уровень опасности по шкале Сигурда: 80%") .Replace("Scientific name: Vir colligerus", "Научное название: Vir colligerus") .Replace("Vir colligerus, or colloquially named Coil-heads, have not been studied extensively due to their extreme unpredictability and dangerous properties. They have been known to combust into flames when being dissected or even deactivated, and they carry dangerously high levels of radioactive particles. Due to this and other reasons, it has been highly speculated they were created as biological weapons of war, although this has not been proven.", "Vir colligerus, или просто пружиноголовые, не изучались подробно из-за их чрезвычайной непредсказуемости и опасных свойств. Известно, что они воспламеняются при разделении тела или даже деактивации, а также содержат опасно высокие уровни радиоактивных частиц. По этим и другим причинам многие предполагают, что они были созданы как биологическое оружие, однако это не было доказано.") .Replace("Coil-heads' visual appearance is that of a bloody mannequin with its head connected by a spring. Their defining behavioral characteristic is to stop when being looked at. However, this does not appear to be a hard-and-fast rule. When they encounter a loud or bright light they sometimes appear to enter a long reset mode.", "Внешне пружиноголовые представляют собой окровавленный манекен с головой на пружине. Их основная поведенческая характеристика — останавливаться, когда на них смотрят. Однако, кажется, это может не являться наистрожайшим правилом. Увидев вспышку яркого света, могут перейти в долгий режим перезагрузки.") .Replace("Just stare at htem or use a stun grenade! - Sigurd", "\nПросто пяльтес на них или используйте светошумовуху! — Сигурд") .Replace("EYELESS DOG", "Безглазая собака (eyeless dog)") .Replace("Scientific name: Leo caecus", "Научное название: Leo caecus") .Replace("A large mammal of the class Saeptivus. They are social, hunting in very large packs. They have also been called \"breathing lions\" for their recognizable sound and large mouths. They are endurance hunters and attempt to make up for their lack of sight with their sense of hearing. It's a popular myth that they often mistake the sounds of their own kind for prey, entering fights within their own packs.", "Крупное млекопитающее класса Saeptivus. Будучи социальными, охотятся очень большими стаями. Их также называют \"дышащими львами\" из-за характерного звука и большой пасти. Они выносливые охотники, у которых получается компенсировать отсутствие зрения чувствительным слухом. Популярен миф о том, что они могут ошибочно принять себе подобных за добычу, вступая в борьбу внутри стаи.") .Replace("Their behaviour is unique from other pack animals in their tendency to spread out far to cover distance. When an eyeless dog has found prey, it roars to alert others in the near vicinity, who will also sound the alarm, sometimes resulting in a kind of chain reaction. Eyeless dogs can be dangerous in swarms. However, they are characteristically clumsy, taking guesses at their prey's exact location which are often incorrect.", "Их поведение уникально среди других стаевых животных своей склонностью к рассредоточению на большие расстояния. Когда безглазая собака чувствует добычу, она издает рычание, чтобы предупредить об этом остальных, которые также бьют тревогу, иногда вызывая своего рода цепную реакцию. Безглазые собаки могут быть опасными в стаях. Тем не менее, им характерна неуклюжесть, когда они проверяют местонахождение своей жертвы и часто оказываются неправы.") .Replace("Manticoils\n\n", "Мантикойл (manticoil)\n\n") .Replace("Sigurd's danger level: 0%\n\n", "Уровень опасности по шкале Сигурда: 0%\n\n") .Replace("Scientific name: Quadrupes-manta", "Научное название: Quadrupes-manta") .Replace("Mantacoils are a passerine bird of the family corvidae. Their bodies are quite large compared to their early descendants, and their wingspan ranges from 55 to 64 inches. Their most defining characteristic is their set of four wings. Their back wings are mostly used to stabilize when at low speed, while their front two wings create the majority of lift. Their round bodies are a striking yellow but with black outlines or stripes along their primary (rear) feathers.", "Мантикойлы — воробьинообразные птицы семейства врановых. Их тела довольно крупные по сравнению с их ранними потомками, а размах крыльев варьируется от 140 до 162 сантиметров. Самой отличительной особенностью является набор из четырех крыльев. Задние крылья в основном используются для стабилизации на низкой скорости, а передние отвечают за взлет. Окрас их круглых тел ярко-желтого цвета с черными контурами или полосками вдоль основных (задних) перьев.") .Replace("Manticoils mostly feed on small insects but can also feed on small rodents. They are highly intelligent and social. They pose little threat and have a generally passive temperament towards humans, although they are capable of transmitting Rabies, Rubenchloria, and Pitt Virus.", "Мантикойлы в основном питаются мелкими насекомыми, но также не брезгуют и мелкими грызунами. Умны и общительны, не представляют особой угрозы и в целом пассивны по отношению к людям, хотя способны передавать бешенство, рубенхлорию и вирус Питта.") .Replace("Spore lizard\n\n", "Споровой ящер (spore lizard)\n\n") .Replace("Sigurd's danger level: i ,dont know probably 5% i just hate this pudgy legged little sh it", "Уровень опасности по шкале Сигурда: я.. я не знаю, мож процентов 5? я просто ненавижу этого пухлоногого зас ранца") .Replace("Scientific name: Lacerta-glomerorum", "Научное название: Lacerta-glomerorum") .Replace("Colloquially named puffers or spore lizards, Lacerta-glomerorum (of the family Alligatoridae) is one of the largest and heaviest reptiles. Despite their large mouths, they are herbivores and do not have a strong bite. The bulbs on their tails are believed to secrete a chemical which attracts and accelerates the growth of the fungus species Lycoperdon perlatum, which it can then shake to release spores as a defense mechanism--an unique example of a mutualistic symbiotic relationship.", "Именуемые фугами или споровыми ящерами, Lacerta-glomerorum (из семейства аллигаторовых) — один из самых крупных и тяжелых рептилий. Несмотря на большой рот, они травоядны и физически не могут сильно укусить. Считается, что шарики на их хвостах выделяют химическое вещество, которое способствует ускоренному росту грибов вида дождевик шиповатый. Также, они могут потрясти хвост вместе с ними, чтобы распылить споры в качестве защитного механизма — уникальный пример мутуалистического симбиоза.") .Replace("Spore lizards have a very timid temperment, tending to avoid all confrontation if possible. If their attempts at threat display are not effective, they may attempt to attack, so it's not recommended to corner or chase one. There are historical records that spore lizards were at least partially domesticated hundreds of years ago, however this effort was set aside by an initiative to harvest their tails for their medicinal properties.", "Споровые ящеры обладают очень робким характером и стараются избегать любых столкновений с другими существами. Если их попытки предупредить об опасности будут проигнорированы, они могут попытаться атаковать, поэтому не рекомендуется загонять их в угол или преследовать. Имеются исторические записи о том, что споровые ящеры были по меньшей мере частично приручены сотни лет назад, однако этот процесс был сорван из-за инициативы по сбору их хвостов в медицинских целях.") .Replace("Bracken -- AKA flower man!", "Папоротник aka человек-цветок! (bracken)") .Replace("it was flower man, you can't say othrwise! i wanted to find his body .You were the cowards", "это был человек-цветок, по-другому и не скажеш! я хотел найти его тело .Вы были трусами") .Replace("Scientific name: Rapax-folium", "Научное название: Rapax-folium") .Replace("There is debate on the genus to which the Bracken belongs. It is a bipedal vertebrate with skin the color and texture of a red beat. The name was coined for what appear to be leaves protruding from its upper spine. The purpose of these is believed to be for intimidation, however not much is known about the specifics of bracken behaviour due to its illusiveness and low population.", "Ведутся споры о том, к какому виду принадлежит папоротник. Это двуногое позвоночное животное с кожей цвета текстуры красной свеклы. Название было придумано из-за чего-то, что напоминает листья, торчащие из верхней части его позвоночника. Считается, что их цель — запугивание, однако об особенностях поведения папоротника мало что известно из-за его скрытности и малой популяции.") .Replace("We know a little from accounts by wildlife experts who have encountered it. is a lone hunter with high intelligence. Its behavior can seem aloof; it exhibits high aggression even when unprovoked, yet it quickly backs off when confronted. However, brackens are known to up their hostility when cornered or simply watched for a long time. For this reason it's recommended to keep an eye on it but not to stare it down. No specimens have been collected dead or alive. It's theorized that upon death their bodies undergo a rapid decomposition process which is unique from other large animals.", "Мы знаем немного из рассказов экспертов по дикой природе, которые с ним сталкивались. Это охотник-одиночка с высоким интеллектом. На первый взгляд может показаться отстраненным; проявляет сильную агрессию даже без провокации, но при столкновении с ним быстро отступает. Однако известно, что папоротники проявляют свою враждебность, если загнать их в угол или просто долго наблюдать за ними. По этой причине рекомендуется держать его в поле зрения, но не удерживать взгляд долго. Не найден ни один живой или мертвый экземпляр. Существует теория, что после смерти их тела подвергаются быстрому процессу разложения, что уникально и отлично от других крупных животных.") .Replace("Circuit Bees\n\n", "Цепная пчела (circuit bee)\n\n") .Replace("Sigurd's danger level: 90%\n\n", "Уровень опасности по шкале Сигурда: 90%\n\n") .Replace("Scientific name: Crabro-coruscus", "Научное название: Crabro-coruscus") .Replace("The circuit bee, also known as red bee, is a eusocial flying insect of the genus Apis, a descendent of the honey bee. Their appearance is quite recognizable from their hairy, red bodies and two sets of wings. Like their ancestors, they are well-known for their intelligent social BEEhavior, large colony size, building wax nests which they use to store honey, and their important role in pollination. Unlike the honey bee, which often chose high places such as trees to construct its hive, red bees create their hives on the ground.", "Цепная пчела, также известная как красная пчела — эусоциальное летающее насекомое рода пчел, потомок медоносной пчелы. Их внешний вид легко уЗЗЗнаваем по мохнатым красным телам и двум парам крыльев. Как и их предки, они известны своим раЗЗЗумным социальным поведением, большим раЗЗЗмером колонии, строительством восковых гнезд, которые они испольЗЗЗуют для хранения меда, а также важной ролью в опылении. В отличие от медоносных пчел, которые для строительства гнеЗЗЗда часто выбирают высокие места (например, деревья), красные пчелы строят свои гнеЗЗЗда прямо на ЗЗЗемле.") .Replace("Red bees are highly defensive. They will leave the nest to attack any creature that comes within several meters, leaving BEEhind only the queen and drone bees. This bold BEEhavior is enabled by their most defining aBEElity, which is their electrostatic charge. Red bees produce friction with the air. They also produce friction by rubbing their two pairs of wings against each other and by rubbing against one another while in the hive. What allows them to create such a surplus of electric field compared to the honey bee is still under research, as they generate a stronger electric field when panicked or angered. This ability is especially useful for them around water.", "Красные пчелы яро ЗЗЗащищают свое гнездо. Они покидают его и нападают на любое существо, которое приблиЗЗЗится к нему, оставляя поЗЗЗади только королеву и трутней. Такое смелое поведение обсусловлено их определяющей способностью — элекстростатическим ЗЗЗарядом. Красные пчелы соЗЗЗдают трение с воздухом, двумя парами крыльев и друг о друга, находясь в гнеЗЗЗде. То, что поЗЗЗволяет им соЗЗЗдавать такой иЗЗЗбыток электрического поля по сравнению с медоносными пчелами, все еще иЗЗЗучается, так как они могут генерировать его еще быстрее и больше, когда находятся в панике или гневе. Эта способность для них особенно полеЗЗЗна около воды.") .Replace("It's BEEst to keep your distance. If a red bee hive is stolen, red bee swarms will enter an onslaught in which they attack any living creature. This destructive BEEhavior will last until they have located the hive or completely exhausted themselves, which can take hours to days. They have BEEn known to leave BEEhind fields of bodies of small rodents, insects and even some larger mammals, and in rare cases they can start fires. Their strong BEEnefits and drawbacks to their ecosystems are highly debated. BEEbated !! - the indomitable Sigurd", "Лучшая стратегия — держать дистанцию. Если гнеЗЗЗдо украдено, рой красных пчел идет в наступление, в ходе которого они атакуют любое живое существо. Такое разрушительное поведение будет продолжаться до тех пор, пока они не найдут гнездо или полностью не истощат себя, что может занять от нескольких часов до нескольких дней. Известно, что они оставляют после себя поля из тел мелких грызунов, насекомых и даже некоторых крупных млекопитающих, а в редких случаях могут вызвать пожар. Их сильные преимущества и недостатки широко обсуждаются.\n\nЗЗЗадолбали !! — несокрушимый Сигурд") .Replace("Baboon hawk\n\n", "Ястреб-бабуин (baboon hawk)\n\n") .Replace("Sigurd's danger level: 75%", "Уровень опасности по шкале Сигурда: 75%") .Replace("Scientific name: Papio-volturius", "Научное название: Papio-volturius") .Replace("Baboon hawks are a primate of the family Cercopithecidae. They are hunchbacked but can stand up to 8 feet on average. Their heads are boney, with bird-like beaks and long horns, which they use like skewers to gore and feed on prey. Their horns are made of keratin instead of bone like the rest of their skulls, and they do not contain nerves or blood vessels. As a result baboon hawks can often break their horns from the force they apply, then fully regrow them within the same season. Baboon hawks partly owe their name to their large wings, which could never carry their large body mass and are used instead for intimidation and protection from the elements.", "Ястребы-бабуины — приматы из семейства мартышковых. Горбатые, но в стоячем положении высота в среднем достигает до 2.4 метров. Головы костистые, с клювами и длинными рогами, которыми они пользуются как шампурами, чтобы пронзать добычу и питаться ею. Рога состоят из кератина, а не из кости, как остальная часть черепа, а также не содержат нервов и кровеносных сосудов. В результате этого, ястребы-бабуины могут сломать свои рога от приложенной силы, а затем полностью отрастить их в течение того же сезона. Своему названию ястребы-бабуины частично обязаны большим крыльям, которые никак не могли бы поднять в небо их большую массу тела, и поэтому они используются для запугивания и защиты от непогоды.") .Replace("The largest baboon hawk troop ever observed was made up of 18 baboon hawks. They are loosely territorial, and much of their behavior is motivated by intimidation and display. They can become collectors, using any flashy or colorful object to mark their territory. As lone scouts, baboon hawks are generally timid and won't attack unless provoked. In greater numbers they can become a great danger; sticking close to others and making yourself seem dangerous are the best ways to prevent an attack. They prefer smaller mammals, but when desperate they are known to use their numbers to attack animals even twice their size, such as eyeless dogs. THEY TOOK M Y PICKLES", "Самая большая когда-либо наблюдавшаяся стая ятребов-бабуинов состояла из 18 особей. Они слабо территориальны, и большая часть их поведения состоит из стратегий запугивания и привлечения внимания. Они могут коллекционировать яркие или красочные предметы, чтобы отметить свою территорию. Будучи разведчиками-одиночками, ястребы-бабуины обычно робки и не нападают, если их не спровоцировать. В больших количествах они могут представлять большую опасность; держаться вместе и показывать свою опасность — лучший способ предотвратить нападение. Они предпочитают более мелких млекопитающих, но в случае отчаяния, как известно, используют свое превосходство по числу особей, чтобы нападать на животных даже вдвое крупнее себя (например, на безглазых собак).\n\nОНИ ЗАБ РАЛИ МОИ ОГУРЧИКИ") .Replace("FOREST KEEPER", "Хранитель леса (forest keeper)") .Replace("Sigurd's danger level: 50%", "Уровень опасности по шкале Сигурда: 50%") .Replace("Scientific name: Satyrid-proceritas", "Научное название: Satyrid-proceritas") .Replace("Believed to share a common ancestor with rapax-folium, these behemoths are called Forest Keepers for the biomes they often inhabit. Their bodies bare markings on their front and back which mimic eyes--this trait is more helpful in their youth, as they are not agile. Their skin is a unique, dense material which hardens further throughout their lives; the large spikes and bumps across their bodies form as a result of aging.", "Возможно произошедшие от общего предка с Rapax-folium, эти гиганты прозваны Хранителями леса из-за местности, в которой они часто обитают. На их телах спереди и сзади имеются отметины, имитирующие глаза — эта особенность более полезна в молодости, так как в старости они неуклюжи. Кожа представляет собой уникальный плотный материал, который твердеет на протяжении всей жизни; большие шипы и шишки по всему телу образуются в результате старения.") .Replace("It's been said Forest Keepers exhibit a curious behavior similar to that of a human child the age of 5 or 6. They will eat anything they find fascinating. Forest Keepers don't actually need to put anything into their mouths, and it's theorized their main source of energy is a process similar to photosynthesis. Still, this makes them relatively dangerous to observe. They can see across long distances, so staying low and making use of cover is a must. They cannot enter small spaces and are not generally destructive, so stay close to shelter or overhangs.", "Говорят, что Хранители леса проявляют любопытство, схожее с таковым у человеческого ребенка в возрасте 5-6 лет. Они едят все, что покажется им интересным. На самом деле Хранителям леса не нужно ничего класть в рот, предполагается, что их основным источником энергии является процесс, аналогичный фотосинтезу. Тем не менее, это делает их относительно опасными для наблюдений. Они могут видеть на далекие расстояния, поэтому необходимо быть на более низком уровне высоты и использовать укрытия. Они не могут проникать в небольшие помещения, и, как правило, не склонны к разрушениям, поэтому держитесь поближе к укрытиям или выступам.") .Replace("Roaming Locusts\n\n", "Бродячая саранча (roaming locusts)\n\n") .Replace("Sigurd's danger level: 0%", "Уровень опасности по шкале Сигурда: 0%") .Replace("Scientific name: Anacridium-vega", "Научное название: Anacridium-vega") .Replace("Known as roaming locusts, this is a species of grasshopper. Unlike some species which are more prone to jump or fly, roaming locusts are almost never grounded and stay close together even when in smaller numbers. They will quickly disperse when a predator disrupts them but are highly attracted to light.", "Это вид кузнечиков, известный как бродячая саранча. В отличие от некоторых видов, которые более склонны передвигаться прыжками или полетом, бродячая саранча практически никогда не приземляется и держится близко друг к другу даже в малом количестве. Они быстро разлетаются, когда их тревожит хищник, но слетаются на свет.") .Replace("SNARE FLEA", "Блохоловка (snare flea)") .Replace("Sigurd's danger level: 30%", "Уровень опасности по шкале Сигурда: 30%") .Replace("Scientific name: Dolus-scolopendra.", "Научное название: Dolus-scolopendra.") .Replace("A very large arthropod of the class chilopoda. Its body produces a silk which it primarily uses to propel itself to places where it is concealed. Its exoskeleton is somewhat fragile, and they can die from long falls. The snare flea does not produce venom, nor does it have a strong bite. It makes up for this weakness with its ability to tighten itself around large prey to suffocate.", "Очень крупное членистоногое из класса губоногих. Ее тело вырабатывает шелк, который она использует в основном для передвижения в укрытие. Ее экзоскелет довольно хрупкий, так что они могут погибнуть при падении с высоты. Блохоловка не вырабатывает яд и не обладает сильным укусом. Такие слабости она компенсирует своей способностью обвиваться вокруг крупной добычи для удушения.") .Replace("The snare flea thrives in dark, warm areas. It cannot survive low temperatures and generally avoids open air and sunlight take the rats outside or just beat the hell otu of them! i think their insides could make a good milkshake,,", "Блохоловка обитает в теплых местах без света. Она пытается держаться подальше от низких температур и обычно избегает открытого пространства и солнечного света.\n\nвыводите этих крыс на улицу или просто отмудохайте! мне кажется из их внутренностей можно сделать неплохой милкшейк,,") .Replace("EARTH LEVIATHAN", "Земляной Левиафан (earth leviathan)") .Replace("Sigurd's danger level: 2% cause they can't hide from the ship cmaeras!!", "Уровень опасности по шкале Сигурда: 2%, потому что они не могут скрыться от кмаер на корабле!!") .Replace("Scientific name: Hemibdella-gigantis", "Научное название: Hemibdella-gigantis") .Replace("The reverently named Earth Leviathan, of the family Piscicolidae, is one of the largest invertibrates found around the Thistle Nebula. None have been captured, so not much is known of their biology.", "Получивший почтенное название Земляной Левиафан из семейства рыбьих пиявок — один из крупнейших беспозвоночных, встречающихся вблизи туманности Чертополох. Ни один из них не был пойман, поэтому об их биологии известно немного.") .Replace("They seem to behave as predators. It's speculated they can burrow as far as 40 meters underground, judging by the incredible excavations they can leave behind. They can detect even the slightest vibrations, and for this reason it's not recommended to stay still if they are nearby; that is a myth. Instead, if you hear them burrowing, retrace your steps.", "Кажется, ведут себя как хищники. Предполагается, что они могут зарываться под землю на глубину до 40 метров, судя по невероятным раскопкам, которые они оставляют после себя. Они способны улавливать даже малейшие вибрации, поэтому не рекомендуется стоять на месте, если они рядом; это миф. Вместо этого, если вы слышите, как они прорываются, вернитесь назад, откуда вы пришли.") .Replace("Bunker spiders\n\n", "Бункерный паук (bunker spider)\n\n") .Replace("Sigurd's danger level: 20%", "Уровень опасности по шкале Сигурда: 20%") .Replace("Scientific name: Mutinum-ficedula", "Научное название: Mutinum-ficedula") .Replace("Bunker spiders, of the genus Theraphosa, are the largest arachnid found in the Thistle Nebula and the second largest ever discovered. It's believed they evolved to prey on large mammals over the course of a measly several hundred years after the Boat made its trip around the Thistle Nebula.", "Бункерные пауки из рода Theraphosa — самые крупные паукообразные, обнаруженные в туманности Чертополох, и вторые по величине из когда-либо обнаруженных. Считается, что они эволюционировали, чтобы охотиться на крупных млекопитающих, в течение жалких нескольких сотен лет после того, как Корабль совершил путешествие вокруг туманности Чертополох.") .Replace("(Refer to: Speculation on Increased Speciation Around the Fading Nebulae)", "(См. также: Спекуляции об усилении видообразования вокруг угасающих туманностей)") .Replace("Bunker spiders produce silk and lay it around their chosen nesting area, then wait for it to be tripped on. They can be seen waiting on walls, often over doorways where prey could enter unaware. If you find a bunker spider 'unprepared' it may freeze as a defensive reaction. In this case they are best left alone. If a bunker spider reacts aggressively, it is best not to fight with ordinary tools. They use their webs to make up for their rather slow movement, so take note of your surroundings. Their webs can be broken easily with any blunt tool.", "Бункерные пауки производят шелк и плетут его вокруг выбранного места для гнезда, а затем ждут, пока в него не попадутся. Их можно увидеть выжидающими на стенах и часто над дверными проемами, где жертва может пройти, ничего не подозревая. Если вы обнаружите бункерного паука \"неподготовленным\", он может замереть на месте в качестве защитной реакции. В этом случае лучше всего будет оставить их в покое. Если бункерный паук ведет себя агрессивно, то лучше не использовать обычные инструменты. Они используют паутину, чтобы компенсировать свое довольно медленное передвижение, поэтому обращайте внимание под ноги. Их паутину можно легко разрушить любым тупым инструментом.") .Replace("Bunker spiders can pose a great danger to humans and urban explorers especially, without a great benefit to their ecosystems. A resulting kill-on-sight order has been informally agreed upon between many states home to the Bunker spider, and it is currently approved by the ITDA as of 10/6/2497.", "Бункерные пауки могут представлять серьезную опасность для людей и особенно для исследователей городов, не принося особой пользы для их экосистем. В результате между многими штатами, где может обитать бункерный паук, был согласован приказ об его убийстве на месте, и в настоящее время он одобрен ITDA от 10/6/2497.") .Replace("JESTER", "Шут (jester)") .Replace("Sigurd's danger level: 90% Get out o fthere before it goes APE!! You cant hide from it, just evacuate", "Уровень опасности по шкале Сигурда: 90%\nУбирайтесь отт уда пока он не ОБЕЗУМЕЛ!! От этого не спрятаться, только эвакуация") .Replace("Scientific name: INSANEUS THINGUS", "Научное название: INSANEUS THINGUS") .Replace("THERE'S NO FREAKING SCIENTIFIC RECORD! good luck, you know as much as us. we just call it the jester", "НЕТ ТУТ НИКАКИХ ГРЕБАНЫХ НАУЧНЫХ ЗАПИСЕЙ! удачи, вы знаете не меньше нашего. мы зовем его просто шут"); return raw == text; } public bool translateDetailSigurd(ref string raw) { string text = raw; raw = raw.Replace("First Log - Aug 22", "Первая запись - 22 авг.").Replace("Date: August 22, 1968", "Дата: 22 августа 1968 г.").Replace("Hello. i am writing this log to keep myself sane. I couldnt find a way to do the most basic thing on this old janky butt computer so I had Desmond add it in, the log feature. til now ive just been adding my own notes to the bestiary whatever i know. My brother said i should keep a journal so im doing what i can! I am writing in a proffessional manner, as these logs could become a historical record, as they will projbably be here for years, just as long as there isnt a clean wipe. that is what desmond saidfd", "Здравствуйте. я пишу этот журнал, чтобы не сойти с ума. Я не смог найти способ сделать самую типичную вещь на этом старом дрянном компьютере, так что я попросил Десмонда добавить ее — функцию журнала. о этого я простл добавлял все что я знал в записки в бестиарии. Мой брат сказал что мне нужно вести дневник, так что я делаю все что в моих силах! Я пишу по проффессиональному, так как эти записи могут стать историческими, и они скорее всенго будут храниться здесь годами, пока не произойдет чистка. так мне сказалдл Десмонд") .Replace("If you are reading it in the future, you are probably from a nother crew. The turnover rate here is enormous, maybe cause this job sucks and every one turns over dead! Maybe I can give some help when I have some expirience. End log", "Если вы читаете это в будущем, вы наверное со всем с другой команды. Текучесть кадров здесь чудовищная, может быть из-за того, что это отстойная работа и каждый раз все мрут! Может быть я смогу чем-то помочь, когда наберусь немнога опыта. Конец записи") .Replace("Oh, our names are: Sigurd (me), Richard, Desmond, Jess.", "А, и наши имена: Сигурд (я), Ричард, Десмонд, Джесс.") .Replace("Smells here! - Aug 24", "Здесь воняет! - 24 авг.") .Replace("gosh, this suit is squeezing me like I'm a gosh damn mummy! im a grown man, give it some space between the legs! it's killing me i'm dying! i hope youre happy dad, I FINALLY got a job. screw you! Everyone here smells. especially Rich. I'm going to throw him in the lake. I don't care what it's made of. i love being on camera duty. oh", "господи, этот костюм сдавливает меня будто чертову мумию! я взрослый мужик, дайте ему хоть немного места между ног! это издевательство я умираю! надеюсь ты счаслив папа, ведь я НАКОНЕЦ-ТО нашел работу. пошел ты! Здесь ото всех воняет. особенно от Рича. Я бы просто сбросил его в озеро. И мне плевать что там за жидкость. мне нравится дежурить на камерах. ох") .Replace("i forgot the date it's August 24, 1968. this keyboard has dsadjilfasqt..f/g;", "я забыл указать дату — 24 августа 1968 г. у этой клавиатуры выфвошдафыйе,,а.п") .Replace("today we found a couple frying pans and a big nail. Worth almost nothing. what is the company even using it for", "сегодня мы нашли пару сковородок и большой гвоздь. Почти ничего не стоит. для чего компания вообще их использует") .Replace("SWING OF THINGS - AUG 27", "КУРС ДЕЛА - 27 АВГ.") .Replace("we got in the \"swing of things\" the past few days. thats what Rich keeps saying, he smells like a rancid tuna can. worst summer camp I've ever been o n. Date is August 27, 1968", "за последние несколько дней мы вошли в \"курс дела\". так постоянно говорит Рич, он пахнет протухшим горьким тунцом. худший летний лагерь в котором я когда либо был. Дата — 27 августа 1968 г") .Replace("we make sure someone always has a shovel for bashing anything that moves, and we always put someone on \"camera duty\" so they can open these big security doors with letters and numbers. ask Desmond the wizard how that works, I think he just", "мы постоянно проверяем чтобы кто-то был с лопатой, чтобы бить все что движется, и мы всегда оставляем кого-то \"дежурить на камерах\" чтобы он мог открывать эти большие механические двери с буквами и цифрами. спросите фокусника Десмонда как это работает, хотя я думаю что он просто") .Replace("types in the code thats on the door", "вводит код с двери") .Replace("Thats it", "Вот и все") .Replace("we sold some goods to the company today at 70% value. i got m y nerves chilled listening to the fuckng PYSCHOTIC soundfs behind the counter. No one else gave any. ??", "сегодня мы продали несколько вещей компании по 70% от всей стоимости. у ме ня мороз по коже от этих ебчих ПСИХОДЕЛИЧЕСКИХ звуков за стойкой. Остальные не обратили внимания. ??") .Replace("Cant ignore that! my flashlight didn't even go back there, the beam just went dark", "Не могу просто проигнорировать это! мой фонарик не пролежал там и секунды, луч света просто исчез во тьме") .Replace("Golden planet - Aug ??", "Золотая планета - ?? авг.") .Replace("I talked ot a voice on the walkie talkie, it was like a part of the screams. he told me the Golden planet actually existed, its not a legend. and he told me it didn't just hit a meteor. He said the planet was swallowed up by the \"beast\", and they were in its body being diggested. i asked what the beast is, and he said he didnt know!. he said it ate the planet and they forgot everything", "Я разговаривал с голосом по рации, он слышался среди криков. он сказал мне что Золотая планета действительно существует, это не легенда. и он сказал мне, что это было не просто падение метеорита. Он сказал что планета была поглощена \"чудовищем\", и они переваривались в его теле. я спросил, что это было за чудовище, и он сказал что не знает!. он сказал что чудовище съело планету, и они просто забылись") .Replace("i couldnt get him to stop talking. but i said he was on the other side of a big wall and i could get him out. i said he was inside the building. and thats when he started freaking out/. i couldn't make out a word, I think he said something about \"spitting out the rinds\" So i just turned it off. what a wack", "я даже не мог заткнуть его. но я сказал ему, что он по другую сторону большой стены и я смогу его вытащить. я сказал, что он внутри здания. и вот теперь он начал паниковатью. я не мог разобрать ни слова, но вроде он сказал что-то про \"выплевывание кожуры\" Так что я просто отключился. что за бред") .Replace("Jess says the golden planet is just a story. I said I KNOW, I'm not an idiot. Well she said i should quit, and she quits if i do. so she s staying", "Джесс говорит, что золотая планета — всего лишь выдумка. Я сказал что ЗНАЮ, я не идиот. Ну, она сказала, что я должен бросить все это дело, и она бросит, если я это сделаю. так што она остается") .Replace("Shady - Aug 31", "Прикрытие - 31 авг.") .Replace("date is August 31, 1968. i got camera duty again, i hate walking on this moon anyway. ahah jokes on them it, just started raining!!! Im just sitting. cant sleep on these tiny beds for ants", "дата — 31 августа 1968 г. я снова дежурю на камерах, все равно ненавижу блуждать по этой луне. ахах вот это прикол, только что дождь начался!!! Я просто сижу. не могу спать на этих крошечных кроватях для муравьев") .Replace("Ive been thinking a lot. i think this job is shady. If youre reading this you probbably got here the same as me. the pay is good, the contract only lasts a season. they ran you through their \"assessmennt exam\" on the phone with a weird voice. you signed the contract on the shuttle with the rest of your crew. But the whole time you didnt talk to anyone. The shuttle was autopiloted, I think the voice on the phone was fake. I;ve had the wrost dreams, I think I just want to go back home. but im not gonna crawl home, crying and scratching on dad's front door. thats not his son. thats not Sigurd!", "Я долго размышлял. походу работа это прикрытие. Если вы читаете это, то скоррее всего вы попали сюда так же как и я. хорошая зарплата, контракт длится всего сезон. они быстренько прогнали вас по \"оценочномму экзамену\" странным голосом по телефону. вы подписали контракт на шаттле вместе с остальными членами вашего экипажа. Но все это время вы ни с кем не разговаривали. Шаттл управлялся на автопилоте, а голос в телефоне думаю был фальшивым. Мне снятся ужасные сныб я бы я просто хочу вернуться домой. но я не буду приползать домой, плакать и царапать папину входную дверь. его сын не такой. это не Сигурд!") .Replace("Sound behind the wall - Sep 4", "Звук за стеной - 4 сент.") .Replace("date: Septermber 4, 1968", "дата: 4 сентября 1968 г.") .Replace("i got woken up early this morning because we were going to the company building to sell our useless garbage. The rate was 120% which Desmond says is rare and he didnt want to miss it, hes been watching it like the stupid stocks", "сегодня утром меня разбудили рано, потому что мы собирались к зданию компании чтобы продать наш бесполезный мусор. Ставка составила 120%, что как сказал Десмонд, редкость, и он не хотел пропустить такое, он следил за этим как за долбанными акциями") .Replace("it still sucks here, Rich still smells like a piece of hsit .i can barely sleep. i heard the wrorst sound behind the wall of the company building, it sounded like crying red faces all churned up and swept away by concrete, like the pestle and bowl my mom crushes up her seeds and spices in. i still hear it. Its a nightmare. no one else heard it. they dont know what to do. Jess thinks i;m \"home sick,\" no im sick of this cheap suit", "здесь по прежнему отстойно, Рич все так же воняет как кусок деьрма .я едва могу заснуть. я слышал ужсасный звук за стеной здания компании, он звучал так будто плачущие красные лица были взбиты и расстолчены бетоном, как ступка и пестик в которых моя мама измельчает семена и специи. я все еще слышу это. Это кошмар. больше никто этого не слышал. они не знают что делать. Джесс думает что яя \"тоскую по дому\", нет- я тоскую по нормальным костюмам") .Replace("Goodbye - Sep 7", "Прощай - 7 сент.") .Replace("we left behiind Rich. we just had one room to check and then we could be done for the day, i couldnt get the door open. And then i looked and Rich wasnt there. It was the fucking wrinkly skin flower head man that walks on two legs! it turned his neck. i heard the crack but he wasnt there. I wanted to find Rich even if he was dead, but they are cowards! their faces are blank like idiots, theres nothing moving in their stupid skulls, all they wanted to do is leave. they were going to leave me too. we all hated Rich but we didnt want this. this isnt worth it, its just not worth it. we got a pair of scissors, a box full of stamps and a bundle of cords to sell for nothing. its not wort h it, what does the company even want it for?", "мы оставили Рича поозади. нам оставалось проверить очередную комнату и тогда мы могли бы закончить на сегодня, у меня не получилось открыть дверь. А потом я посмотрел и Рича уже не было. Это был блядский человек с морщинистой кожей и головой в форме цветка который ходил на двух ногах! это нечто свернуло ему шею. я услышал треск, но его там уже не было. Я хотел найти Рича даже мертвым, но они трусы! их лица безэмоциональны как у идиотов, в их тупых черепах ничего не щелкнуло, все что они хотели сделать – это уйти. они были готовы бросить и меня тоже. мы все ненавидели Рича но не хотели такого. это того не стоит, оно просто того не стоит. у нас есть пара ножниц, заполненная марками коробка и связка шнуров, которые продадутся за бесценок. это того не сто ит, зачем это вообще нужно компании?") .Replace("the date we last saw Rich is September 7, 1968", "дата, когда мы в последний раз видели Рича – 7 сентября 1968 г.") .Replace("Screams - Sep 13", "Крики - 13 сент.") .Replace("date: September 13, 1968", "дата: 13 сентября 1968 г.") .Replace("for some reason i was the one who had to call the company number to report the acciddent. they were too scared to do it. It was the same fake voice i remember from the interview on the phone at home and the stupid training videos. but it heard what i said i think, cause it said they would contact the family and find a replacement and something e lse. It talked so fast", "получилось както так, что именно мне пришлось позвонить по номеру компании, чтобы сообщить о происшествии. они были слишком напуганы, чтобы сделать это. Это был тот же фальшивый голос, который я слышал на собеседовании по телефону дома и на дурацких обучающих видео. но он вроде услышал то что я доносил до него, потому что он сказал, что они свяжутся с семьей и найдут замену и что-то тако е. Он говорил очень быстро") .Replace("I learned you can hear the screams all the time in the walkie talkie when you;re at the wall of the Company building. they didnt believe me, well now they do. It sounds just like when i heard it a couple weeks ago. They want to quit. I said I'm not a coward. I just got this job", "Я понял, что крики можно постоянно слышать по рации когда стоиш у стены здания Компании. они мне не верили, чтош, теперь верят. Звуки точно такие же как и когда я слышал это пару недель назад. Они хотят уйти. Я сказал что я не трус. Я только недавно получил эту работу") .Replace("Idea - Sep 19", "Идея - 19 сент.") .Replace("date: September 19, 1968", "дата: 19 сентября 1968 г.") .Replace("the past weekend it feels like Desmond and Jess woke up. we;re supposed to get our fourth member of the crew in a few days. We arent taking any risks anymore, we dont get as much but it feels safer, and ive gotten better sleep. but its still ass. i can still smell Rich i swear to gosh he smelled that bad", "с прошлых выходных Десмонд и Джесс вроде как пришли в себя. через несвколько дней к нам присоединится четвертый член экипажа. Мы больше не рискуем, мы получаем меньше, но так безопаснее и я стал лучше спать. но это все равно та еще задница. я все еще чувствую вонь Рича, клянусь, боже как же он омерзительно вонял") .Replace("i was talking about how the voice on the phone sounded fake. Then Desmond got this weird idea. he's the wizard and all so he thinks theres a way to use the phone call i made to the company number to find ourt where the voice comes from. i dont know why hed want to do that but he seems serious. He;s been using the terminal a lot.", "я говорил о том, как голос по телефону звучал фальшиво. Потом Десмонду пришла в голову эта странная идея. он волшебник и все такое, поэтому он думает что можно использовать звонок, который я сделал на номер компании, чтобы выяснить откулда идет этот голос. не знаю почему он захотел это сделать, но он кажется подошел к этому серьезно. Он, много времени проводит за терминалом.") .Replace("Nonsense - Sep 27", "Бред - 27 сент.") .Replace("September 27, 1968", "27 сентября 1968 г.") .Replace("desmond wants me to writ e down what we figured out and keep my \"nonsense to a minimum\". So im going to put SO MUCH of my non sense. screw him. The new crew member is named Lucas and he is so confused and scared a ll the time, what a baby, at least he doesnt smell like a monster.", "десмонд хочет чтобы я запис ал что мы выяснили и чтобы \"бредил поменьше\". Так что я собираюсь бредить ПОБОЛЬШЕ. клал я на него. Нового члена экипажа зовут Лукас и он постоянно такой растерянный и испуганный, что за ребенок, зато хоть не воняет как чудище.") .Replace("its been so sunny even though its september, and these suits dont take it well", "несмотря на сентябрь, было очень солнечно и эти костюмы не предусмотрены для такого") .Replace("ok so desmond \"traced the call\" and found out theres a group of people somewhere else that pretends to call us from the company building. they are across the whole solar system !! why would they be so far away.", "короче Десмонд \"отследил звонок\" и выяснил что где-то есть группа людей, которые делают вид будто звонят нам из здания компании. они раскиданы по всей солнечной системе !! почему они так далеко.") .Replace("Desmond says he doesnt know, but i think. What if there really is a big monster in the company building like the voice told me on the wlakie talkie? They trapped it, and we feed it to keep it tame. i just wanted a stupid job!!!!!", "Десмонд говорит что не уверен, но я так считаю. А что если в здании компании и правда сидит огромное чудовище как и сказал мне голос по рцаии? Они поймали его в ловушку, а мы его кормим чтобы усмирять. я просто хотел тупую работу!!!!!") .Replace("Hiding - Sep 30", "Сокрытие - 30 сент.") .Replace("September 30, 1968", "30 сентября 1968 г.") .Replace("i keep having bad dreams about the Company building where the Company breaks out of that giant concrete wall. But i dont know if it looks like anything, i just think its really big and fast. We cant figure out a way to know if the voices on the phone are real, desmond says its too far away. i asked him if he could ttake control of the autopilot and he said im crazy and that could kill us. yes i am crazy desmond", "мне постоянно снятся кошмары про здание Компании, где Компания вырывается из этой гигантской бетонной стены. Но я не знаю похоже ли оно хоть на что то, у меня есть догадки, что оно очень огромное и быстрое. Мы не можем придумать как выяснить, реальные ли голоса в телефоне, десмонд говорит это слишком далеко. я спросил не мог бы он ввзять под контроль автопил
BepInEx/plugins/XUnity.AutoTranslator/ExIni.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using Microsoft.Win32; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyInformationalVersion("GIT master [cf85ca6f3fc361cf48bf56107e4cec9102b7f5eb] ")] [assembly: AssemblyTitle("ExIni")] [assembly: Guid("b8adf1ac-aade-485a-8997-14c4b42e0a8b")] [assembly: AssemblyDescription("Extended INI File Handler")] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyFileVersion("1.0.2.1")] [assembly: AssemblyCompany("Usagirei")] [assembly: AssemblyProduct("ExIni")] [assembly: ComVisible(false)] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCopyright("Copyright © Usagirei 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("1.0.2.1")] namespace ExIni; public class IniComment { public List<string> Comments { get; set; } public IniComment() { Comments = new List<string>(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Comments.Count; i++) { string text = Comments[i]; string value = ((i < Comments.Count - 1) ? (";" + text + Environment.NewLine) : (";" + text)); stringBuilder.Append(value); } return stringBuilder.ToString(); } public void Append(params string[] comments) { Comments.AddRange(comments); } } public class IniFile { private readonly IniComment _comments; private readonly List<IniSection> _sections; public IniSection this[string sec] => CreateSection(sec); public IniComment Comments => _comments; public List<IniSection> Sections => _sections; public IniFile() { _comments = new IniComment(); _sections = new List<IniSection>(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < Sections.Count; i++) { IniSection iniSection = Sections[i]; if (iniSection.Comments.Comments.Any()) { stringBuilder.AppendLine(iniSection.Comments.ToString()); } stringBuilder.AppendLine(iniSection.ToString()); foreach (IniKey key in iniSection.Keys) { if (key.Comments.Comments.Any()) { stringBuilder.AppendLine(key.Comments.ToString()); } stringBuilder.AppendLine(key.ToString()); } if (i < Sections.Count - 1) { stringBuilder.AppendLine(); } } if (Comments.Comments.Any()) { stringBuilder.AppendLine(); stringBuilder.AppendLine(Comments.ToString()); } return stringBuilder.ToString(); } public IniSection CreateSection(string section) { IniSection section2 = GetSection(section); if (section2 != null) { return section2; } IniSection iniSection = new IniSection(section); _sections.Add(iniSection); return iniSection; } public bool DeleteSection(string section) { if (!HasSection(section)) { return false; } Sections.Remove(GetSection(section)); return true; } public IniSection GetSection(string section) { if (!HasSection(section)) { return null; } return _sections.FirstOrDefault((IniSection iniSection) => iniSection.Section == section); } public bool HasSection(string section) { return _sections.Any((IniSection iniSection) => iniSection.Section == section); } public void Merge(IniFile ini) { Comments.Append(ini.Comments.Comments.ToArray()); foreach (IniSection section in ini.Sections) { IniSection iniSection = this[section.Section]; iniSection.Comments.Append(section.Comments.Comments.ToArray()); foreach (IniKey key in section.Keys) { IniKey iniKey = iniSection[key.Key]; iniKey.Comments.Append(key.Comments.Comments.ToArray()); iniKey.Value = key.Value; } } } public void Save(string filePath) { string directoryName = Path.GetDirectoryName(filePath); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(filePath, ToString(), Encoding.UTF8); } public static IniFile FromFile(string iniString) { return IniParser.Parse(File.ReadAllText(iniString)); } public static IniFile FromString(string iniString) { return IniParser.Parse(iniString); } } public class IniKey { private readonly IniComment _comments; public IniComment Comments => _comments; public string Key { get; set; } public string RawValue { get; set; } public string Value { get { return Resolve(RawValue); } set { RawValue = value; } } public IniKey(string key, string value = null) { Key = key; Value = value; _comments = new IniComment(); } public override string ToString() { return $"{Key}={RawValue}"; } private static string GetEnvironment(string env) { return Environment.ExpandEnvironmentVariables(env); } private static string GetRegistry(string path) { string directoryName = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); if (string.IsNullOrEmpty(directoryName)) { return null; } return Registry.GetValue(directoryName, fileName, string.Empty)?.ToString(); } private static string Resolve(string value) { if (value == null) { return null; } Regex regex = new Regex("\\$\\((?<reg>.*)\\)"); Regex regex2 = new Regex("%.*%"); while (regex.IsMatch(value) || regex2.IsMatch(value)) { value = regex.Replace(value, (Match match) => GetRegistry(match.Groups["reg"].Value)); value = GetEnvironment(value); } return value; } } internal class IniParser { private static readonly Regex CommentRegex = new Regex("^;(?<com>.*)"); private static readonly Regex KeyRegex = new Regex("^(?<key>[\\w\\s]+)=(?<val>.*)$"); private static readonly Regex SectionRegex = new Regex("^\\[(?<sec>[\\w\\s]+)\\]$"); private static readonly Regex VarRegex = new Regex("^\\@(?<key>[\\w\\s]+)=(?<val>.*)$"); public static IniFile Parse(string iniString) { IniFile iniFile = new IniFile(); string[] array = (from line in iniString.Split(new char[1] { '\n' }) let trimmed = line.Trim() select trimmed.TrimEnd(new char[1] { '\r' })).ToArray(); List<string> list = new List<string>(); IniSection iniSection = null; bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i]; if (string.IsNullOrEmpty(text)) { continue; } if (IsComment(text)) { string comment = GetComment(text); list.Add(comment); if (IsVariable(comment)) { string[] variable = GetVariable(comment); string variable2 = variable[0]; string value = variable[1]; Environment.SetEnvironmentVariable(variable2, value); } flag = true; } else if (IsSection(text)) { iniSection = iniFile[GetSection(text)]; if (flag) { iniSection.Comments.Append(list.ToArray()); list.Clear(); flag = false; } } else if (IsKey(text)) { if (iniSection == null) { throw new Exception($"{i}: Sectionless Key Value Pair"); } string[] key = GetKey(text); string key2 = key[0]; string value2 = key[1]; if (flag) { iniSection[key2].Comments.Append(list.ToArray()); list.Clear(); flag = false; } iniSection[key2].Value = value2; } } if (flag) { iniFile.Comments.Append(list.ToArray()); } return iniFile; } private static string GetComment(string line) { return CommentRegex.Match(line).Groups["com"].Value; } private static string[] GetKey(string line) { Match match = KeyRegex.Match(line); return new string[2] { match.Groups["key"].Value, match.Groups["val"].Value }; } private static string GetSection(string line) { return SectionRegex.Match(line).Groups["sec"].Value; } private static string[] GetVariable(string line) { Match match = VarRegex.Match(line); return new string[2] { match.Groups["key"].Value, match.Groups["val"].Value }; } private static bool IsComment(string line) { return CommentRegex.IsMatch(line); } private static bool IsKey(string line) { return KeyRegex.IsMatch(line); } private static bool IsSection(string line) { return SectionRegex.IsMatch(line); } private static bool IsVariable(string line) { return VarRegex.IsMatch(line); } } public class IniSection { private readonly IniComment _comments; private readonly List<IniKey> _keys; public IniKey this[string key] => CreateKey(key); public IniComment Comments => _comments; public List<IniKey> Keys => _keys; public string Section { get; set; } public IniSection(string section) { Section = section; _comments = new IniComment(); _keys = new List<IniKey>(); } public override string ToString() { return $"[{Section}]"; } public IniKey CreateKey(string key) { IniKey key2 = GetKey(key); if (key2 != null) { return key2; } IniKey iniKey = new IniKey(key); _keys.Add(iniKey); return iniKey; } public IniKey GetKey(string key) { if (!HasKey(key)) { return null; } return _keys.FirstOrDefault((IniKey iniKey) => iniKey.Key == key); } public bool HasKey(string key) { return _keys.Any((IniKey iniKey) => iniKey.Key == key); } public bool DeleteKey(string key) { if (!HasKey(key)) { return false; } Keys.Remove(GetKey(key)); return true; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BaiduTranslate.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BaiduTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BaiduTranslate")] [assembly: AssemblyTitle("BaiduTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BaiduTranslate; internal class BaiduTranslateEndpoint : HttpEndpoint { private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string> { { "en", "en" }, { "ja", "jp" }, { "jp", "jp" }, { "zh", "zh" }, { "zh-Hans", "zh" }, { "zh-CN", "zh" }, { "zh-Hant", "cht" }, { "zh-TW", "cht" }, { "ko", "kor" }, { "kor", "kor" }, { "fra", "fra" }, { "fr", "fra" }, { "spa", "spa" }, { "es", "spa" }, { "ara", "ara" }, { "ar", "ara" }, { "bg", "bul" }, { "bul", "bul" }, { "et", "est" }, { "est", "est" }, { "da", "dan" }, { "dan", "dan" }, { "fi", "fin" }, { "fin", "fin" }, { "ro", "rom" }, { "rom", "rom" }, { "sl", "slo" }, { "slo", "slo" }, { "vi", "vie" }, { "vie", "vie" }, { "sv", "swe" }, { "swe", "swe" }, { "th", "th" }, { "ru", "ru" }, { "pt", "pt" }, { "de", "de" }, { "it", "it" }, { "el", "el" }, { "nl", "nl" }, { "pl", "pl" }, { "cs", "cs" }, { "hu", "hu" } }; private static readonly string HttpServicePointTemplateUrl = "https://api.fanyi.baidu.com/api/trans/vip/translate?q={0}&from={1}&to={2}&appid={3}&salt={4}&sign={5}"; private static readonly MD5 HashMD5 = MD5.Create(); private string _appId; private string _appSecret; private float _delay; private float _lastRequestTimestamp; public override string Id => "BaiduTranslate"; public override string FriendlyName => "Baidu Translator"; private string FixLanguage(string lang) { if (SupportedLanguages.TryGetValue(lang, out var value)) { return value; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) _appId = context.GetOrCreateSetting<string>("Baidu", "BaiduAppId", ""); _appSecret = context.GetOrCreateSetting<string>("Baidu", "BaiduAppSecret", ""); _delay = context.GetOrCreateSetting<float>("Baidu", "DelaySeconds", 1f); if (string.IsNullOrEmpty(_appId)) { throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Id which has not been provided."); } if (string.IsNullOrEmpty(_appSecret)) { throw new EndpointInitializationException("The BaiduTranslate endpoint requires an App Secret which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.fanyi.baidu.com" }); if (!SupportedLanguages.ContainsKey(context.SourceLanguage)) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.ContainsKey(context.DestinationLanguage)) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { float realtimeSinceStartup = TimeHelper.realtimeSinceStartup; float num = realtimeSinceStartup - _lastRequestTimestamp; if (num < _delay) { float num2 = _delay - num; object obj = CoroutineHelper.CreateWaitForSecondsRealtime(num2); if (obj != null) { yield return obj; } else { float end = realtimeSinceStartup + num2; while (realtimeSinceStartup < end) { yield return null; } } } _lastRequestTimestamp = TimeHelper.realtimeSinceStartup; } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown string text = DateTime.UtcNow.Millisecond.ToString(); string text2 = CreateMD5(_appId + ((ITranslationContextBase)context).UntranslatedText + text + _appSecret); XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpServicePointTemplateUrl, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), _appId, text, text2)); val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8"; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; if (data.StartsWith("{\"error")) { return; } JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); Enumerator enumerator = ((JSONNode)((JSONNode)val.AsObject)["trans_result"].AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsObject)["dst"]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append("\n"); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); context.Complete(text2); } private static string CreateMD5(string input) { byte[] bytes = Encoding.UTF8.GetBytes(input); byte[] array = HashMD5.ComputeHash(bytes); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < array.Length; i++) { stringBuilder.Append(array[i].ToString("X2")); } return stringBuilder.ToString().ToLower(); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslate.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BingTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BingTranslate")] [assembly: AssemblyTitle("BingTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BingTranslate; public class BingTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto-detect", "af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant", "hr", "cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr", "de", "el", "ht", "he", "hi", "mww", "hu", "is", "id", "it", "ja", "sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt", "nb", "fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn", "sk", "sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr", "uk", "ur", "vi", "cy", "yua" }; private static readonly string HttpsServicePointTemplateUrl = "https://www.bing.com/ttranslatev3?isVertical=1&&IG={0}&IID={1}.{2}"; private static readonly string HttpsServicePointTemplateUrlWithoutIG = "https://www.bing.com/ttranslatev3?isVertical=1"; private static readonly string HttpsTranslateUserSite = "https://www.bing.com/translator"; private static readonly string RequestTemplate = "&fromLang={1}&text={0}&to={2}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[1] { "*/*" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] Referers = new string[1] { "https://bing.com/translator" }; private static readonly string[] Origins = new string[1] { "https://www.bing.com" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string[] ContentTypes = new string[1] { "application/x-www-form-urlencoded" }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)]; private static readonly string Origin = Origins[RandomNumbers.Next(Origins.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)]; private CookieContainer _cookieContainer; private bool _hasSetup; private string _ig; private string _iid; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public override string Id => "BingTranslate"; public override string FriendlyName => "Bing Translator"; public BingTranslateEndpoint() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh": return "zh-Hans"; case "zh-TW": return "zh-Hant"; case "auto": return "auto-detect"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) context.DisableCertificateChecksFor(new string[1] { "www.bing.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 0; _hasSetup = true; IEnumerator enumerator = SetupIGAndIID(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown _translationCount++; string text = null; text = ((_ig != null && _iid != null) ? string.Format(HttpsServicePointTemplateUrl, _ig, _iid, _translationCount) : HttpsServicePointTemplateUrlWithoutIG); string text2 = string.Format(RequestTemplate, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); XUnityWebRequest val = new XUnityWebRequest("POST", text, text2); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray)[0]["translations"].AsArray)[0]["text"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); context.Complete(text2); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (Referer != null && isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = Referer; } if (Origin != null && isTranslationRequest) { request.Headers["Origin"] = Origin; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } if (ContentType != null && isTranslationRequest) { request.Headers[HttpRequestHeader.ContentType] = ContentType; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; _cookieContainer.Add(newCookies); } public IEnumerator SetupIGAndIID() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up BingTranslate IG. Proceeding without..."); yield break; } InspectResponse(response); try { string data = response.Data; _ig = Lookup("\",IG:\"", data); _iid = Lookup("data-iid=\"", data); if (_ig == null || _iid == null) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up BingTranslate IG/IID. Proceeding without..."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up BingTranslate IG. Proceeding without..."); } } private string Lookup(string lookFor, string html) { int num = html.IndexOf(lookFor); if (num > -1) { int num2 = num + lookFor.Length; int num3 = html.IndexOf("\"", num2); if (num2 > -1 && num3 > -1) { return html.Substring(num2, num3 - num2); } } return null; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/BingTranslateLegitimate.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("BingTranslateLegitimate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BingTranslateLegitimate")] [assembly: AssemblyTitle("BingTranslateLegitimate")] [assembly: AssemblyVersion("1.0.0.0")] namespace BingTranslateLegitimate; public class BingTranslateLegitimateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "af", "ar", "bn", "bs", "bg", "yue", "ca", "zh-Hans", "zh-Hant", "hr", "cs", "da", "nl", "en", "et", "fj", "fil", "fi", "fr", "de", "el", "ht", "he", "hi", "mww", "hu", "is", "id", "it", "ja", "sw", "tlh", "tlh-Qaak", "ko", "lv", "lt", "mg", "ms", "mt", "nb", "fa", "pl", "pt", "otq", "ro", "ru", "sm", "sr-Cyrl", "sr-Latn", "sk", "sl", "es", "sv", "ty", "ta", "te", "th", "to", "tr", "uk", "ur", "vi", "cy", "yua" }; private static readonly string HttpsServicePointTemplateUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from={0}&to={1}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[1] { "application/json" }; private static readonly string[] ContentTypes = new string[1] { "application/json" }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string ContentType = ContentTypes[RandomNumbers.Next(ContentTypes.Length)]; private string _key; public override string Id => "BingTranslateLegitimate"; public override string FriendlyName => "Bing Translator (Authenticated)"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh": return "zh-Hans"; case "zh-TW": return "zh-Hant"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("BingLegitimate", "OcpApimSubscriptionKey", ""); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The BingTranslateLegitimate endpoint requires an API key which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.cognitive.microsofttranslator.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("["); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]); stringBuilder.Append("{\"Text\":\""); stringBuilder.Append(value); stringBuilder.Append("\"}"); if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i) { stringBuilder.Append(","); } } stringBuilder.Append("]"); XUnityWebRequest val = new XUnityWebRequest("POST", string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage)), stringBuilder.ToString()); if (Accept != null) { val.Headers[HttpRequestHeader.Accept] = Accept; } if (ContentType != null) { val.Headers[HttpRequestHeader.ContentType] = ContentType; } val.Headers["Ocp-Apim-Subscription-Key"] = _key; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONArray asArray = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { JSONNode obj = ((JSONNode)((JSONNode)asArray)[i].AsObject)["translations"]; object obj2; if (obj == null) { obj2 = null; } else { JSONNode obj3 = ((JSONNode)obj.AsArray)[0]; obj2 = ((obj3 != null) ? ((object)((JSONNode)obj3.AsObject)["text"])?.ToString() : null); } string text = (string)obj2; string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/CustomTranslate.dll
Decompiled a year agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("CustomTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomTranslate")] [assembly: AssemblyTitle("CustomTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace CustomTranslate; internal class CustomTranslateEndpoint : HttpEndpoint { private static readonly string ServicePointTemplateUrl = "{0}?from={1}&to={2}&text={3}"; private string _endpoint; private string _friendlyName; public override string Id => "CustomTranslate"; public override string FriendlyName => _friendlyName; public CustomTranslateEndpoint() { _friendlyName = "Custom"; } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) _endpoint = context.GetOrCreateSetting<string>("Custom", "Url", ""); if (string.IsNullOrEmpty(_endpoint)) { throw new EndpointInitializationException("The custom endpoint requires a url which has not been provided."); } Uri uri = new Uri(_endpoint); context.DisableCertificateChecksFor(new string[1] { uri.Host }); _friendlyName = _friendlyName + " (" + uri.Host + ")"; } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(string.Format(ServicePointTemplateUrl, _endpoint, ((ITranslationContextBase)context).SourceLanguage, ((ITranslationContextBase)context).DestinationLanguage, Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText))); context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { context.Complete(((IHttpResponseInspectionContext)context).Response.Data); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/DeepLTranslate.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("DeepLTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DeepLTranslate")] [assembly: AssemblyTitle("DeepLTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace DeepLTranslate; public class DeepLTranslate : ExtProtocolEndpoint { private const float MinimumMinDelaySeconds = 1f; private const float MinimumMaxDelaySeconds = 3f; private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "zh", "ko" }; public override string Id => "DeepLTranslate"; public override string FriendlyName => "DeepL Translator"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 25; protected override string ConfigurationSectionName => "DeepL"; private string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); ((ExtProtocolEndpoint)this).MinDelay = context.GetOrCreateSetting<float>("DeepL", "MinDelaySeconds", 2f); if (((ExtProtocolEndpoint)this).MinDelay < 1f) { XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MinDelaySeconds below {1f} second(s). Setting MinDelaySeconds={1f}"); context.SetSetting<float>("DeepL", "MinDelaySeconds", 1f); } ((ExtProtocolEndpoint)this).MaxDelay = context.GetOrCreateSetting<float>("DeepL", "MaxDelaySeconds", 6f); if (((ExtProtocolEndpoint)this).MaxDelay < 3f) { XuaLogger.AutoTranslator.Warn($"[DeepL] Cannot set MaxDelaySeconds below {3f} second(s). Setting MaxDelaySeconds={3f}"); context.SetSetting<float>("DeepL", "MaxDelaySeconds", 3f); } if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None); } } public class DeepLTranslateLegitimate : ExtProtocolEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "bg", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "hu", "it", "ja", "lt", "lv", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "zh", "ko" }; public override string Id => "DeepLTranslateLegitimate"; public override string FriendlyName => "DeepL Translator (Authenticated)"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 25; protected override string ConfigurationSectionName => "DeepLLegitimate"; private string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } string orCreateSetting = context.GetOrCreateSetting<string>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "ApiKey", ""); bool orCreateSetting2 = context.GetOrCreateSetting<bool>(((ExtProtocolEndpoint)this).ConfigurationSectionName, "Free", false); if (string.IsNullOrEmpty(orCreateSetting)) { throw new EndpointInitializationException("The endpoint requires an API key which has not been provided."); } ((ExtProtocolEndpoint)this).ConfigForExternalProcess = string.Join("\n", orCreateSetting, orCreateSetting2.ToString()); ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("DeepLTranslate.ExtProtocol.ExtDeepLTranslateLegitimate, DeepLTranslate.ExtProtocol"), Base64FormattingOptions.None); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/ezTransXP.dll
Decompiled a year agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Microsoft.Win32; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("ezTransXP")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ezTransXP")] [assembly: AssemblyTitle("ezTransXP")] [assembly: AssemblyVersion("1.0.0.0")] namespace ezTransXP; public class ezTransXPEndpoint : ExtProtocolEndpoint { public override string Id => "ezTransXP"; public override string FriendlyName => "ezTransXP"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 50; public override void Initialize(IInitializationContext context) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) string defaultInstallationPath = GetDefaultInstallationPath(); string text = context.GetOrCreateSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath); if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath)) { context.SetSetting<string>("ezTrans", "InstallationPath", defaultInstallationPath); text = defaultInstallationPath; } context.DisableSpamChecks(); string text2 = Path.Combine(context.TranslatorDirectory, "FullNET\\ezTransXP.ExtProtocol.exe"); if (!File.Exists(text2)) { throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'"); } ((ExtProtocolEndpoint)this).ExecutablePath = text2; ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); if (context.SourceLanguage != "ja") { throw new EndpointInitializationException("Current implementation only supports japanese-to-korean."); } if (context.DestinationLanguage != "ko") { throw new EndpointInitializationException("Current implementation only supports japanese-to-korean."); } } public static string GetDefaultInstallationPath() { try { return (string)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\ChangShin\\ezTrans", "FilePath", null); } catch { return null; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Common.ExtProtocol.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using XUnity.AutoTranslator.Plugin.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Common.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Common.ExtProtocol")] [assembly: AssemblyTitle("Common.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } public static bool forceASCII; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { get { yield break; } } public IEnumerable<JSONNode> DeepChildren { get { foreach (JSONNode child in Children) { foreach (JSONNode deepChild in child.DeepChildren) { yield return deepChild; } } } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, out result)) { return result; } return 0.0; } set { Value = value.ToString(); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { return new JSONString(s); } public static implicit operator string(JSONNode d) { if (!(d == null)) { return d.Value; } return null; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { if (!(d == null)) { return d.AsDouble; } return 0.0; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { if (!(d == null)) { return d.AsFloat; } return 0f; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { if (!(d == null)) { return d.AsInt; } return 0; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { if (!(d == null)) { return d.AsBool; } return false; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } if (!flag) { return a.Equals(b); } return false; } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) { if (quoted) { ctx.Add(tokenName, token); return; } string text = token.ToLower(); switch (text) { case "false": case "true": ctx.Add(tokenName, text == "true"); return; case "null": ctx.Add(tokenName, null); return; } if (double.TryParse(token, out var result)) { ctx.Add(tokenName, result); } else { ctx.Add(tokenName, token); } } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string text = ""; bool flag = false; bool flag2 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } text = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; flag2 = false; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; default: stringBuilder.Append(aJSON[i]); break; case '\n': case '\r': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } return jSONNode; } } public class JSONArray : JSONNode { private List<JSONNode> m_List = new List<JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { get { foreach (JSONNode item in m_List) { yield return item; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } } public class JSONObject : JSONNode { private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.ContainsKey(aKey)) { return m_Dict[aKey]; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { get { foreach (KeyValuePair<string, JSONNode> item in m_Dict) { yield return item.Value; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (!string.IsNullOrEmpty(aKey)) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(); } set { if (double.TryParse(value, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data); } private static bool IsNumeric(object value) { if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte)) { return value is byte; } return true; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node; private string m_Key; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { JSONArray jSONArray = new JSONArray(); jSONArray.Add(value); Set(jSONArray); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, value); Set(jSONObject); } } public override int AsInt { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override float AsFloat { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0f; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override double AsDouble { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0.0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override bool AsBool { get { JSONBool aVal = new JSONBool(aData: false); Set(aVal); return false; } set { JSONBool aVal = new JSONBool(value); Set(aVal); } } public override JSONArray AsArray { get { JSONArray jSONArray = new JSONArray(); Set(jSONArray); return jSONArray; } } public override JSONObject AsObject { get { JSONObject jSONObject = new JSONObject(); Set(jSONObject); return jSONObject; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private void Set(JSONNode aVal) { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; } public override void Add(JSONNode aItem) { JSONArray jSONArray = new JSONArray(); jSONArray.Add(aItem); Set(jSONArray); } public override void Add(string aKey, JSONNode aItem) { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, aItem); Set(jSONObject); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } } namespace Common.ExtProtocol { public interface IExtTranslateEndpoint { Task Translate(ITranslationContext context); void Initialize(string config); } public interface ITranslationContext : ITranslationContextBase { void Complete(string translatedText); void Complete(string[] translatedTexts); } public interface ITranslationContextBase { string UntranslatedText { get; } string[] UntranslatedTexts { get; } UntranslatedTextInfo UntranslatedTextInfo { get; } UntranslatedTextInfo[] UntranslatedTextInfos { get; } string SourceLanguage { get; } string DestinationLanguage { get; } object UserState { get; set; } void Fail(string reason, Exception exception); void Fail(string reason); } public class TranslationContext : ITranslationContext, ITranslationContextBase { private string[] _untranslatedTexts; public string UntranslatedText => UntranslatedTexts[0]; public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((UntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public UntranslatedTextInfo UntranslatedTextInfo => UntranslatedTextInfos[0]; public UntranslatedTextInfo[] UntranslatedTextInfos { get; } public string SourceLanguage { get; } public string DestinationLanguage { get; } internal bool IsDone { get; private set; } public string[] TranslatedTexts { get; private set; } public string ErrorMessage { get; private set; } public Exception Error { get; private set; } public object UserState { get; set; } public TranslationContext(TransmittableUntranslatedTextInfo[] untranslatedTexts, string sourceLanguage, string destinationLanguage) { UntranslatedTextInfos = untranslatedTexts.Select((TransmittableUntranslatedTextInfo x) => new UntranslatedTextInfo(x)).ToArray(); SourceLanguage = sourceLanguage; DestinationLanguage = destinationLanguage; } public void Complete(string translatedText) { Complete(new string[1] { translatedText }); } public void Complete(string[] translatedTexts) { if (IsDone) { return; } try { if (translatedTexts.Length == 0) { FailContext("Received empty translation from translator.", null); return; } for (int i = 0; i < translatedTexts.Length; i++) { if (string.IsNullOrEmpty(translatedTexts[0])) { FailContext("Received empty translation from translator.", null); return; } } CompleteContext(translatedTexts); } finally { IsDone = true; } } public void Fail(string reason, Exception exception) { if (IsDone) { return; } try { FailContext(reason, exception); throw new TranslationContextException(); } finally { IsDone = true; } } public void Fail(string reason) { if (IsDone) { return; } try { FailContext(reason, null); throw new TranslationContextException(); } finally { IsDone = true; } } public void FailWithoutThrowing(string reason, Exception exception) { if (IsDone) { return; } try { FailContext(reason, exception); } finally { IsDone = true; } } internal void FailIfNotCompleted() { if (!IsDone) { FailWithoutThrowing("The translation request was not completed before returning from translator.", null); } } public void FailContext(string reason, Exception exception) { ErrorMessage = reason; Error = exception; } public void CompleteContext(string[] translatedTexts) { TranslatedTexts = translatedTexts; } } [Serializable] internal class TranslationContextException : Exception { public TranslationContextException() { } public TranslationContextException(string message) : base(message) { } public TranslationContextException(string message, Exception inner) : base(message, inner) { } protected TranslationContextException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public class UntranslatedTextInfo { public string[] ContextBefore { get; } public string UntranslatedText { get; } public string[] ContextAfter { get; } public UntranslatedTextInfo(TransmittableUntranslatedTextInfo untranslatedTextInfo) { ContextBefore = untranslatedTextInfo.ContextBefore; UntranslatedText = untranslatedTextInfo.UntranslatedText; ContextAfter = untranslatedTextInfo.ContextAfter; } public UntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } } } namespace Common.ExtProtocol.Utilities { public static class JsonHelper { public static string Unescape(string str) { if (str == null) { return null; } StringBuilder stringBuilder = new StringBuilder(str); bool flag = false; for (int i = 0; i < stringBuilder.Length; i++) { char c = stringBuilder[i]; if (flag) { bool flag2 = true; char c2 = '\0'; switch (c) { case 'b': c2 = '\b'; break; case 'f': c2 = '\f'; break; case 'n': c2 = '\n'; break; case 'r': c2 = '\r'; break; case 't': c2 = '\t'; break; case '"': c2 = '"'; break; case '\\': c2 = '\\'; break; case 'u': c2 = 'u'; break; default: flag2 = false; break; } if (flag2) { if (c2 == 'u') { char value = (char)int.Parse(new string(new char[4] { stringBuilder[i + 1], stringBuilder[i + 2], stringBuilder[i + 3], stringBuilder[i + 4] }), NumberStyles.HexNumber); stringBuilder.Remove(--i, 6); stringBuilder.Insert(i, value); } else { stringBuilder.Remove(--i, 2); stringBuilder.Insert(i, c2); } } flag = false; } else if (c == '\\') { flag = true; } } return stringBuilder.ToString(); } public static string Escape(string str) { if (str == null || str.Length == 0) { return ""; } int length = str.Length; StringBuilder stringBuilder = new StringBuilder(length + 4); for (int i = 0; i < length; i++) { char c = str[i]; switch (c) { case '"': case '\\': stringBuilder.Append('\\'); stringBuilder.Append(c); break; case '\b': stringBuilder.Append("\\b"); break; case '\t': stringBuilder.Append("\\t"); break; case '\n': stringBuilder.Append("\\n"); break; case '\f': stringBuilder.Append("\\f"); break; case '\r': stringBuilder.Append("\\r"); break; case '\u0085': stringBuilder.Append("\\u0085"); break; case '\u2028': stringBuilder.Append("\\u2028"); break; case '\u2029': stringBuilder.Append("\\u2029"); break; default: stringBuilder.Append(c); break; } } return stringBuilder.ToString(); } } public static class StringBuilderExtensions { public static bool EndsWithWhitespaceOrNewline(this StringBuilder builder) { if (builder.Length == 0) { return true; } char c = builder[builder.Length - 1]; if (!char.IsWhiteSpace(c)) { return c == '\n'; } return true; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/DeepLTranslate.ExtProtocol.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Common.ExtProtocol; using Common.ExtProtocol.Utilities; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SimpleJSON; [assembly: AssemblyProduct("DeepLTranslate.ExtProtocol")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCompany("DeepLTranslate.ExtProtocol")] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyTitle("DeepLTranslate.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DeepLTranslate.ExtProtocol { [Serializable] public class BlockedException : Exception { public BlockedException() { } public BlockedException(string message) : base(message) { } public BlockedException(string message, Exception inner) : base(message, inner) { } protected BlockedException(SerializationInfo info, StreamingContext context) : base(info, context) { } } public static class HttpResponseMessageExtensions { public static void ThrowIfBlocked(this HttpResponseMessage msg) { if (msg.StatusCode == HttpStatusCode.TooManyRequests) { throw new Exception("Too many requests!"); } } } public class ExtDeepLTranslate : IExtTranslateEndpoint { private class UntranslatedTextInfo { public string UntranslatedText { get; set; } public List<TranslationPart> TranslationParts { get; set; } } public class TranslationPart { public bool IsTranslatable { get; set; } public string Value { get; set; } } private static readonly Regex NewlineSplitter; private static readonly DateTime Epoch; private static readonly string HttpsServicePointTemplateUrl; private static readonly string HttpsTranslateUserSite; private static readonly string HttpsTranslateStateSetup; private static readonly Random RandomNumbers; private static readonly string[] Accepts; private static readonly string[] AcceptLanguages; private static readonly string[] Referers; private static readonly string[] Origins; private static readonly string Accept; private static readonly string AcceptLanguage; private static readonly string Referer; private static readonly string Origin; private SemaphoreSlim _sem; private HttpClient _client; private HttpClientHandler _handler; private bool _hasSetup; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); private long _id; static ExtDeepLTranslate() { NewlineSplitter = new Regex("([\\s]*[\\r\\n]+[\\s]*)"); Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); HttpsServicePointTemplateUrl = "https://www2.deepl.com/jsonrpc"; HttpsTranslateUserSite = "https://www.deepl.com/translator"; HttpsTranslateStateSetup = "https://www.deepl.com/PHP/backend/clientState.php?request_type=jsonrpc&il=EN"; RandomNumbers = new Random(); Accepts = new string[1] { "*/*" }; AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; Referers = new string[1] { "https://www.deepl.com/translator" }; Origins = new string[1] { "https://www.deepl.com" }; Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; Referer = Referers[RandomNumbers.Next(Referers.Length)]; Origin = Origins[RandomNumbers.Next(Origins.Length)]; ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; } public ExtDeepLTranslate() { _sem = new SemaphoreSlim(1, 1); } public void Initialize(string config) { } public void Reset() { _hasSetup = false; } private void CreateClientAndHandler() { if (_client != null) { _client.Dispose(); } _handler = new HttpClientHandler(); _handler.CookieContainer = new CookieContainer(); _handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; _client = new HttpClient(_handler, disposeHandler: true); _client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"); } private static string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public async Task EnsureSetupState() { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _hasSetup = true; _id = 10000 * (long)(10000.0 * RandomNumbers.NextDouble()); CreateClientAndHandler(); await SetupState(); } } public async Task SetupState() { _translationCount = 0; await RequestWebsite(); await GetClientState(); } private void AddHeaders(HttpRequestMessage request, HttpContent content, bool isTranslationRequest) { if (AcceptLanguage != null) { request.Headers.TryAddWithoutValidation("Accept-Language", AcceptLanguage); } if (Accept != null) { request.Headers.TryAddWithoutValidation("Accept", Accept); } if (Referer != null && isTranslationRequest) { request.Headers.TryAddWithoutValidation("Referer", Referer); } if (Origin != null && isTranslationRequest) { request.Headers.TryAddWithoutValidation("Origin", Origin); } if (isTranslationRequest && content != null) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } request.Headers.TryAddWithoutValidation("DNT", "1"); } public async Task Translate(ITranslationContext context) { _ = 3; try { await _sem.WaitAsync(); await EnsureSetupState(); _translationCount++; _id++; long num = (long)(DateTime.UtcNow - Epoch).TotalMilliseconds; long num2 = 1L; StringBuìlder stringBuìlder = new StringBuìlder(); stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"LMT_handle_jobs\",\"params\":{\"jobs\":["); List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>(); UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos; foreach (UntranslatedTextInfo val in untranslatedTextInfos2) { List<TranslationPart> list = (from x in NewlineSplitter.Split(val.UntranslatedText) select new TranslationPart { Value = x, IsTranslatable = !NewlineSplitter.IsMatch(x) }).ToList(); string[] array = (from x in list where x.IsTranslatable select x.Value).ToArray(); for (int j = 0; j < array.Length; j++) { string text = array[j]; stringBuìlder.Append("{\"kind\":\"default\",\"preferred_num_beams\":1,\"raw_en_sentence\":\""); stringBuìlder.Append(JsonHelper.Escape(text)); HashSet<string> hashSet = new HashSet<string>(); stringBuìlder.Append("\",\"raw_en_context_before\":["); bool flag = false; string[] contextBefore = val.ContextBefore; foreach (string text2 in contextBefore) { if (!hashSet.Contains(text2)) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(text2)); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag = true; } } for (int l = 0; l < j; l++) { if (!hashSet.Contains(array[l])) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(array[l])); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag = true; } } if (flag) { stringBuìlder.Remove(stringBuìlder.Length - 1, 1); } stringBuìlder.Append("],\"raw_en_context_after\":["); bool flag2 = false; for (int m = j + 1; m < array.Length; m++) { if (!hashSet.Contains(array[m])) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(array[m])); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag2 = true; } } contextBefore = val.ContextAfter; foreach (string text3 in contextBefore) { if (!hashSet.Contains(text3)) { stringBuìlder.Append("\""); stringBuìlder.Append(JsonHelper.Escape(text3)); stringBuìlder.Append("\""); stringBuìlder.Append(","); flag2 = true; } } if (flag2) { stringBuìlder.Remove(stringBuìlder.Length - 1, 1); } stringBuìlder.Append("]},"); num2 += text.Count((char c) => c == 'i'); } untranslatedTextInfos.Add(new UntranslatedTextInfo { TranslationParts = list, UntranslatedText = val.UntranslatedText }); } stringBuìlder.Remove(stringBuìlder.Length - 1, 1); long num3 = num + (num2 - num % num2); stringBuìlder.Append("],\"lang\":{\"user_preferred_langs\":[\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant()); stringBuìlder.Append("\",\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant()); stringBuìlder.Append("\"],\"source_lang_user_selected\":\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant()); stringBuìlder.Append("\",\"target_lang\":\""); stringBuìlder.Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant()); stringBuìlder.Append("\"},\"priority\":-1,\"timestamp\":"); stringBuìlder.Append(num3.ToString(CultureInfo.InvariantCulture)); stringBuìlder.Append("},\"id\":"); stringBuìlder.Append(_id); stringBuìlder.Append("}"); StringContent content = new StringContent(stringBuìlder.ToString()); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, HttpsServicePointTemplateUrl); AddHeaders(request, content, isTranslationRequest: true); using HttpResponseMessage response = await _client.PostAsync(HttpsServicePointTemplateUrl, content); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context); } catch (BlockedException) { Reset(); throw; } finally { _sem.Release(); } } private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context) { JSONArray asArray = JSON.Parse(data)["result"]["translations"].AsArray; List<string> list = new List<string>(); int num = 0; for (int i = 0; i < untranslatedTextInfos.Count; i++) { List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts; StringBuilder stringBuilder = new StringBuilder(); foreach (TranslationPart item in translationParts) { if (item.IsTranslatable) { JSONArray asArray2 = ((JSONNode)asArray)[num++]["beams"].AsArray; if (((JSONNode)asArray2).Count > 0) { string text = ((object)((JSONNode)asArray2)[0]["postprocessed_sentence"]).ToString(); string value = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); stringBuilder.Append(value); } } else { stringBuilder.Append(item.Value); } } string text2 = stringBuilder.ToString(); if (string.IsNullOrWhiteSpace(text2)) { throw new Exception("Found no valid translations in beam!"); } list.Add(text2); } context.Complete(list.ToArray()); } public async Task RequestWebsite() { using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateUserSite); AddHeaders(request, null, isTranslationRequest: false); using HttpResponseMessage response = await _client.SendAsync(request); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); } public async Task GetClientState() { _id++; StringBuìlder stringBuìlder = new StringBuìlder(); stringBuìlder.Append("{\"jsonrpc\":\"2.0\",\"method\":\"getClientState\",\"params\":{\"v\":\"20180814\"},\"id\":"); stringBuìlder.Append(_id); stringBuìlder.Append("}"); StringContent content = new StringContent(stringBuìlder.ToString()); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, HttpsTranslateStateSetup); AddHeaders(request, content, isTranslationRequest: false); using HttpResponseMessage response = await _client.SendAsync(request); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); } public void Dispose() { _client?.Dispose(); } } public class ExtDeepLTranslateLegitimate : IExtTranslateEndpoint { private class UntranslatedTextInfo { public string UntranslatedText { get; set; } public List<TranslationPart> TranslationParts { get; set; } } public class TranslationPart { public bool IsTranslatable { get; set; } public string Value { get; set; } } private class TranslationResponse { public List<Translation> translations { get; set; } } private class Translation { public string detected_source_language { get; set; } public string text { get; set; } } private string _httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}"; private HttpClient _client; private HttpClientHandler _handler; private string _apiKey; static ExtDeepLTranslateLegitimate() { ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; } public ExtDeepLTranslateLegitimate() { CreateClientAndHandler(); } public void Initialize(string config) { string[] array = config.Split(new char[1] { '\n' }, StringSplitOptions.None); _apiKey = array[0]; if (string.Equals(array[1], "true", StringComparison.OrdinalIgnoreCase)) { _httpsServicePointTemplateUrl = "https://api-free.deepl.com/v2/translate?auth_key={0}"; } else { _httpsServicePointTemplateUrl = "https://api.deepl.com/v2/translate?auth_key={0}"; } } private void CreateClientAndHandler() { if (_client != null) { _client.Dispose(); } _handler = new HttpClientHandler(); _handler.CookieContainer = new CookieContainer(); _handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; _client = new HttpClient(_handler, disposeHandler: true); _client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("XUnity", "5.3.0")); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); } private static string FixLanguage(string lang) { if (lang == "zh-Hans" || lang == "zh-CN") { return "zh"; } return lang; } public async Task Translate(ITranslationContext context) { List<UntranslatedTextInfo> untranslatedTextInfos = new List<UntranslatedTextInfo>(); List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); list.Add(new KeyValuePair<string, string>("auth_key", _apiKey)); list.Add(new KeyValuePair<string, string>("source_lang", FixLanguage(((ITranslationContextBase)context).SourceLanguage).ToUpperInvariant())); list.Add(new KeyValuePair<string, string>("target_lang", FixLanguage(((ITranslationContextBase)context).DestinationLanguage).ToUpperInvariant())); list.Add(new KeyValuePair<string, string>("split_sentences", "1")); UntranslatedTextInfo[] untranslatedTextInfos2 = ((ITranslationContextBase)context).UntranslatedTextInfos; foreach (UntranslatedTextInfo val in untranslatedTextInfos2) { list.Add(new KeyValuePair<string, string>("text", val.UntranslatedText)); untranslatedTextInfos.Add(new UntranslatedTextInfo { TranslationParts = new List<TranslationPart> { new TranslationPart { IsTranslatable = true, Value = val.UntranslatedText } }, UntranslatedText = val.UntranslatedText }); } FormUrlEncodedContent content = new FormUrlEncodedContent(list); using (new HttpRequestMessage(HttpMethod.Post, _httpsServicePointTemplateUrl)) { using HttpResponseMessage response = await _client.PostAsync(string.Format(_httpsServicePointTemplateUrl, _apiKey), content); response.ThrowIfBlocked(); response.EnsureSuccessStatusCode(); ExtractTranslation(await response.Content.ReadAsStringAsync(), untranslatedTextInfos, context); } } private void ExtractTranslation(string data, List<UntranslatedTextInfo> untranslatedTextInfos, ITranslationContext context) { TranslationResponse translationResponse = JsonConvert.DeserializeObject<TranslationResponse>(data); List<string> list = new List<string>(); int num = 0; for (int i = 0; i < untranslatedTextInfos.Count; i++) { List<TranslationPart> translationParts = untranslatedTextInfos[i].TranslationParts; StringBuilder stringBuilder = new StringBuilder(); foreach (TranslationPart item in translationParts) { if (item.IsTranslatable) { string text = translationResponse.translations[num++].text; stringBuilder.Append(text); } else { stringBuilder.Append(item.Value); } } string text2 = stringBuilder.ToString(); if (string.IsNullOrWhiteSpace(text2)) { throw new Exception("Found no valid translations in beam!"); } list.Add(text2); } context.Complete(list.ToArray()); } public void Dispose() { _client?.Dispose(); } } } namespace System.Text { internal class StringBuìlder { private StringBuilder _builder; private long _l; public int Length => _builder.Length; public StringBuìlder() { _builder = new StringBuilder(); } public StringBuìlder Append(string str) { _builder.Append(str); return this; } public StringBuìlder Append(char c) { _builder.Append(c); return this; } public StringBuìlder Append(int i) { _builder.Append(i); return this; } public StringBuìlder Append(long l) { _builder.Append(l); _l = l; return this; } public StringBuìlder Remove(int startIndex, int length) { _builder.Remove(startIndex, length); return this; } public override string ToString() { return _builder.ToString().Replace("hod\":\"", ((_l + 3) % 13 == 0L || (_l + 5) % 29 == 0L) ? "hod\" : \"" : "hod\": \""); } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/GoogleTranslateCompat.ExtProtocol.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using Common.ExtProtocol; using Common.ExtProtocol.Utilities; using Http.ExtProtocol; using SimpleJSON; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyTitle("GoogleTranslateCompat.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateCompat.ExtProtocol; internal class GoogleTranslateCompatTranslate : ExtHttpEndpoint { public static readonly string UserAgent_Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"; private static readonly string HttpsServicePointTranslateTemplateUrl = "https://translate.googleapis.com/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}"; private static readonly string HttpsTranslateUserSite = "https://translate.google.com"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] Referers = new string[2] { null, "https://translate.google.com/" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string Referer = Referers[RandomNumbers.Next(Referers.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private CookieContainer _cookieContainer; private bool _hasSetup; private long m = 427761L; private long s = 1179739010L; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public GoogleTranslateCompatTranslate() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override async Task OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _hasSetup = true; await SetupTKK(); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown _translationCount++; string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts); XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text))); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); val = ((JSONNode)val.AsArray)[0]; if (val.IsNull) { context.Complete(((ITranslationContextBase)context).UntranslatedText); return; } Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[0]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int i = 0; i < untranslatedTexts.Length; i++) { int num2 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length; string text3 = string.Empty; for (int j = 0; j < num2; j++) { if (num >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text4 = array[num++]; text3 += text4; if (j != num2 - 1) { text3 += "\n"; } } list.Add(text3); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(HttpsTranslateUserSite); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = UserAgent_Chrome_Win10_Latest; if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (Referer != null && isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = Referer; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; foreach (Cookie item in newCookies) { item.Domain = ".googleapis.com"; } _cookieContainer.Add(newCookies); } public async Task SetupTKK() { _cookieContainer = new CookieContainer(); XUnityWebResponse val3; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); val3 = await val.SendAsync(val2); } catch (Exception) { return; } if (val3.Error != null || val3.Data == null) { return; } InspectResponse(val3); try { string data = val3.Data; string[] array = new string[2] { "tkk:'", "TKK='" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("'", num2); string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' }); if (array2.Length == 2) { m = long.Parse(array2[0]); s = long.Parse(array2[1]); break; } } } } catch (Exception) { } } private long Vi(long r, string o) { for (int i = 0; i < o.Length; i += 3) { long num = o[i + 2]; num = ((num >= 97) ? (num - 87) : (num - 48)); num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num)); r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num)); } return r; } private string Tk(string r) { List<long> list = new List<long>(); for (int i = 0; i < r.Length; i++) { long num = r[i]; if (128 > num) { list.Add(num); continue; } if (2048 > num) { list.Add((num >> 6) | 0xC0); } else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1])) { num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]); list.Add((num >> 18) | 0xF0); list.Add(((num >> 12) & 0x3F) | 0x80); } else { list.Add((num >> 12) | 0xE0); list.Add(((num >> 6) & 0x3F) | 0x80); } list.Add((0x3F & num) | 0x80); } long num2 = m; for (int j = 0; j < list.Count; j++) { num2 += list[j]; num2 = Vi(num2, "+-a^+6"); } num2 = Vi(num2, "+-3^+b+-f"); num2 ^= s; if (0 > num2) { num2 = (0x7FFFFFFF & num2) + 2147483648u; } num2 %= 1000000; return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Http.ExtProtocol.dll
Decompiled a year agousing System; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using Common.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Http.ExtProtocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Http.ExtProtocol")] [assembly: AssemblyTitle("Http.ExtProtocol")] [assembly: AssemblyVersion("1.0.0.0")] namespace Http.ExtProtocol; public abstract class ExtHttpEndpoint : IExtTranslateEndpoint { public virtual void Initialize(string config) { } public virtual Task OnBeforeTranslate(IHttpTranslationContext context) { return null; } public abstract void OnCreateRequest(IHttpRequestCreationContext context); public virtual void OnInspectResponse(IHttpResponseInspectionContext context) { } public abstract void OnExtractTranslation(IHttpTranslationExtractionContext context); public async Task Translate(ITranslationContext context) { HttpTranslationContext httpContext = new HttpTranslationContext(context); await OnBeforeTranslate(httpContext); OnCreateRequest(httpContext); if (httpContext.Request == null) { httpContext.Fail("No request object was provided by the translator."); } XUnityWebResponse xUnityWebResponse2 = (httpContext.Response = await new XUnityWebClient().SendAsync(httpContext.Request)); OnInspectResponse(httpContext); if (xUnityWebResponse2.Error != null) { httpContext.Fail("Error occurred while retrieving translation.", xUnityWebResponse2.Error); } if (xUnityWebResponse2.Data == null) { httpContext.Fail("Error occurred while retrieving translation. Nothing was returned."); } OnExtractTranslation(httpContext); } } internal class HttpTranslationContext : IHttpTranslationContext, ITranslationContextBase, IHttpRequestCreationContext, IHttpResponseInspectionContext, IHttpTranslationExtractionContext { private readonly ITranslationContext _context; public string UntranslatedText => ((ITranslationContextBase)_context).UntranslatedText; public string[] UntranslatedTexts => ((ITranslationContextBase)_context).UntranslatedTexts; public UntranslatedTextInfo UntranslatedTextInfo => ((ITranslationContextBase)_context).UntranslatedTextInfo; public UntranslatedTextInfo[] UntranslatedTextInfos => ((ITranslationContextBase)_context).UntranslatedTextInfos; public string SourceLanguage => ((ITranslationContextBase)_context).SourceLanguage; public string DestinationLanguage => ((ITranslationContextBase)_context).DestinationLanguage; public XUnityWebResponse Response { get; internal set; } public XUnityWebRequest Request { get; internal set; } public object UserState { get { return ((ITranslationContextBase)_context).UserState; } set { ((ITranslationContextBase)_context).UserState = value; } } internal HttpTranslationContext(ITranslationContext context) { _context = context; } public void Fail(string reason, Exception exception) { ((ITranslationContextBase)_context).Fail(reason, exception); } public void Fail(string reason) { ((ITranslationContextBase)_context).Fail(reason); } void IHttpRequestCreationContext.Complete(XUnityWebRequest request) { Request = request; } void IHttpTranslationExtractionContext.Complete(string translatedText) { _context.Complete(translatedText); } void IHttpTranslationExtractionContext.Complete(string[] translatedTexts) { _context.Complete(translatedTexts); } } public interface IHttpRequestCreationContext : IHttpTranslationContext, ITranslationContextBase { void Complete(XUnityWebRequest request); } public interface IHttpResponseInspectionContext : IHttpTranslationContext, ITranslationContextBase { XUnityWebRequest Request { get; } XUnityWebResponse Response { get; } } public interface IHttpTranslationContext : ITranslationContextBase { } public interface IHttpTranslationExtractionContext : IHttpResponseInspectionContext, IHttpTranslationContext, ITranslationContextBase { void Complete(string translatedText); void Complete(string[] translatedTexts); } public static class UserAgents { public static readonly string Chrome_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"; public static readonly string Chrome_Win7_Latest = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"; public static readonly string Firefox_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"; public static readonly string Edge_Win10_Latest = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763"; } public class XUnityWebClient : WebClient { private HttpStatusCode? _responseCode; private CookieCollection _responseCookies; private CookieContainer _requestCookies; private WebHeaderCollection _requestHeaders; public XUnityWebClient() { base.Encoding = System.Text.Encoding.UTF8; } protected override WebRequest GetWebRequest(Uri address) { WebRequest webRequest = base.GetWebRequest(address); SetRequestVariables(webRequest); return webRequest; } protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) { WebResponse webResponse = base.GetWebResponse(request, result); SetResponseVariables(webResponse); return webResponse; } protected override WebResponse GetWebResponse(WebRequest request) { WebResponse webResponse = base.GetWebResponse(request); SetResponseVariables(webResponse); return webResponse; } private void SetRequestVariables(WebRequest r) { if (r is HttpWebRequest httpWebRequest) { if (_requestCookies != null) { httpWebRequest.CookieContainer = _requestCookies; } if (_requestHeaders != null) { base.Headers = _requestHeaders; } httpWebRequest.ReadWriteTimeout = 50000; httpWebRequest.Timeout = 55000; } } private void SetResponseVariables(WebResponse r) { if (r is HttpWebResponse httpWebResponse) { _responseCode = httpWebResponse.StatusCode; _responseCookies = httpWebResponse.Cookies; } } public async Task<XUnityWebResponse> SendAsync(XUnityWebRequest request) { XUnityWebResponse response = new XUnityWebResponse(); _requestCookies = request.Cookies; _requestHeaders = request.Headers; if (request.Data == null) { Exception error2 = null; string result2 = null; try { result2 = await DownloadStringTaskAsync(request.Address); } catch (Exception ex) { error2 = ex; } response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2); } else { Exception error2 = null; string result2 = null; try { result2 = await UploadStringTaskAsync(request.Address, request.Method, request.Data); } catch (Exception ex2) { error2 = ex2; } response.SetCompleted(_responseCode.Value, result2, base.ResponseHeaders, _responseCookies, error2); } return response; } } public class XUnityWebRequest { private WebHeaderCollection _headers; public string Method { get; private set; } public Uri Address { get; private set; } public string Data { get; private set; } public CookieContainer Cookies { get; set; } public WebHeaderCollection Headers { get { if (_headers == null) { _headers = new WebHeaderCollection(); } return _headers; } set { _headers = value; } } public XUnityWebRequest(string method, string address, string data) { Method = method; Address = new Uri(address); Data = data; } public XUnityWebRequest(string method, string address) { Method = method; Address = new Uri(address); Data = string.Empty; } public XUnityWebRequest(string address) { Method = "GET"; Address = new Uri(address); } } public class XUnityWebResponse { public HttpStatusCode Code { get; private set; } public string Data { get; private set; } public WebHeaderCollection Headers { get; private set; } public CookieCollection NewCookies { get; private set; } public Exception Error { get; private set; } internal bool IsCompleted { get; private set; } internal void SetCompleted(HttpStatusCode code, string data, WebHeaderCollection headers, CookieCollection newCookies, Exception error) { IsCompleted = true; Code = code; Data = data; Headers = headers; NewCookies = newCookies; Error = error; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/Newtonsoft.Json.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("13.0.1.25517")] [assembly: AssemblyInformationalVersion("13.0.1+ae9fe44e1323e91bcbd185ca1a14099fba7c021f")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = num & _mask; for (Entry entry = _entries[num3]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; _mask = num; } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (text.IndexOf('.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } public class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling
BepInEx/plugins/XUnity.AutoTranslator/Translators/FullNET/XUnity.AutoTranslator.Plugin.ExtProtocol.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyVersion("1.0.1.0")] namespace XUnity.AutoTranslator.Plugin.ExtProtocol; public class ConfigurationMessage : ProtocolMessage { public static readonly string Type = "4"; public string Config { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); Config = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.Write(Config); } } public static class ExtProtocolConvert { private static readonly Dictionary<string, Type> IdToType; private static readonly Dictionary<Type, string> TypeToId; static ExtProtocolConvert() { IdToType = new Dictionary<string, Type>(); TypeToId = new Dictionary<Type, string>(); Register(TranslationRequest.Type, typeof(TranslationRequest)); Register(TranslationResponse.Type, typeof(TranslationResponse)); Register(TranslationError.Type, typeof(TranslationError)); Register(ConfigurationMessage.Type, typeof(ConfigurationMessage)); } public static void Register(string id, Type type) { IdToType[id] = type; TypeToId[type] = id; } public static string Encode(ProtocolMessage message) { StringWriter stringWriter = new StringWriter(); string value = TypeToId[message.GetType()]; stringWriter.WriteLine(value); message.Encode(stringWriter); return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None); } public static ProtocolMessage Decode(string message) { StringReader stringReader = new StringReader(Encoding.UTF8.GetString(Convert.FromBase64String(message))); string key = stringReader.ReadLine(); ProtocolMessage obj = (ProtocolMessage)Activator.CreateInstance(IdToType[key]); obj.Decode(stringReader); return obj; } } public abstract class ProtocolMessage { public Guid Id { get; set; } internal abstract void Decode(TextReader reader); internal abstract void Encode(TextWriter writer); } public enum StatusCode { OK = 0, Blocked = 1, Unknown = 1000 } public class TranslationError : ProtocolMessage { public static readonly string Type = "3"; public string Reason { get; set; } public StatusCode FailureCode { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); FailureCode = (StatusCode)int.Parse(reader.ReadLine()); Reason = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine((int)FailureCode); writer.Write(Reason); } } public class TranslationRequest : ProtocolMessage { public static readonly string Type = "1"; private string[] _untranslatedTexts; public string SourceLanguage { get; set; } public string DestinationLanguage { get; set; } public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); SourceLanguage = reader.ReadLine(); DestinationLanguage = reader.ReadLine(); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num]; for (int i = 0; i < num; i++) { TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo(); transmittableUntranslatedTextInfo.Decode(reader); array[i] = transmittableUntranslatedTextInfo; } UntranslatedTextInfos = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(SourceLanguage); writer.WriteLine(DestinationLanguage); writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture)); TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos; for (int i = 0; i < untranslatedTextInfos.Length; i++) { untranslatedTextInfos[i].Encode(writer); } } } public class TranslationResponse : ProtocolMessage { public static readonly string Type = "2"; public string[] TranslatedTexts { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } TranslatedTexts = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture)); string[] translatedTexts = TranslatedTexts; foreach (string s in translatedTexts) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } } public class TransmittableUntranslatedTextInfo { public string[] ContextBefore { get; set; } public string UntranslatedText { get; set; } public string[] ContextAfter { get; set; } public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } public TransmittableUntranslatedTextInfo() { } internal void Encode(TextWriter writer) { string[] contextBefore = ContextBefore; writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextBefore != null) { string[] contextBefore2 = ContextBefore; foreach (string s in contextBefore2) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } string[] contextAfter = ContextAfter; writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextAfter != null) { string[] contextBefore2 = ContextAfter; foreach (string s2 in contextBefore2) { string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None); writer.WriteLine(value2); } } string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None); writer.WriteLine(value3); } internal void Decode(TextReader reader) { int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } ContextBefore = array; int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array2 = new string[num2]; for (int j = 0; j < num2; j++) { string s2 = reader.ReadLine(); string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2)); array2[j] = string2; } ContextAfter = array2; string s3 = reader.ReadLine(); string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3)); UntranslatedText = string3; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslate.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Extensions; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslate")] [assembly: AssemblyTitle("GoogleTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslate; public class GoogleTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "romaji", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string DefaultApiBackend = "https://translate.googleapis.com"; private static readonly string DefaultUserBackend = "https://translate.google.com"; private static readonly string HttpsServicePointTranslateTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl={1}&dt=t&tk={2}&q={3}"; private static readonly string HttpsServicePointRomanizeTemplateUrl = "/translate_a/single?client=webapp&sl={0}&tl=en&dt=rm&tk={1}&q={2}"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] Accepts = new string[3] { null, "*/*", "application/json" }; private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string[] AcceptCharsets = new string[2] { null, Encoding.UTF8.WebName }; private static readonly string Accept = Accepts[RandomNumbers.Next(Accepts.Length)]; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private static readonly string AcceptCharset = AcceptCharsets[RandomNumbers.Next(AcceptCharsets.Length)]; private string _selectedApiBackend; private string _selectedUserBackend; private string _httpsServicePointTranslateTemplateUrl; private string _httpsServicePointRomanizeTemplateUrl; private CookieContainer _cookieContainer; private bool _hasSetup; private long m = 427761L; private long s = 1179739010L; private int _translationsPerRequest = 10; private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); public override string Id => "GoogleTranslate"; public override string FriendlyName => "Google! Translate"; public override int MaxTranslationsPerRequest => _translationsPerRequest; public GoogleTranslateEndpoint() { _cookieContainer = new CookieContainer(); } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if (context.DestinationLanguage == "romaji") { _translationsPerRequest = 1; } _selectedApiBackend = DefaultApiBackend; _selectedUserBackend = DefaultUserBackend; string orCreateSetting = context.GetOrCreateSetting<string>("Google", "ServiceUrl"); if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting)) { _selectedApiBackend = orCreateSetting; _selectedUserBackend = orCreateSetting; _httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl; _httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl; XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten."); } else { _selectedApiBackend = DefaultApiBackend; _selectedUserBackend = DefaultUserBackend; _httpsServicePointTranslateTemplateUrl = _selectedApiBackend + HttpsServicePointTranslateTemplateUrl; _httpsServicePointRomanizeTemplateUrl = _selectedApiBackend + HttpsServicePointRomanizeTemplateUrl; } context.DisableCertificateChecksFor(new string[2] { new Uri(_selectedApiBackend).Host, new Uri(_selectedUserBackend).Host }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _hasSetup = true; IEnumerator enumerator = SetupTKK(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown _translationCount++; string text = string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts); XUnityWebRequest val = ((!(((ITranslationContextBase)context).DestinationLanguage == "romaji")) ? new XUnityWebRequest(string.Format(_httpsServicePointTranslateTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Tk(text), Uri.EscapeDataString(text))) : new XUnityWebRequest(string.Format(_httpsServicePointRomanizeTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), Tk(text), Uri.EscapeDataString(text)))); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); context.Complete(val); } public override void OnInspectResponse(IHttpResponseInspectionContext context) { InspectResponse(context.Response); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) bool flag = ((ITranslationContextBase)context).DestinationLanguage == "romaji"; int num = (flag ? 3 : 0); string data = ((IHttpResponseInspectionContext)context).Response.Data; JSONNode val = JSON.Parse(data); StringBuilder stringBuilder = new StringBuilder(data.Length); val = ((JSONNode)val.AsArray)[0]; if (val.IsNull && flag) { context.Complete(((ITranslationContextBase)context).UntranslatedText); return; } Enumerator enumerator = ((JSONNode)val.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { string text = ((object)((JSONNode)JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray)[num]).ToString(); text = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text); } string text2 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num2 = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int i = 0; i < untranslatedTexts.Length; i++) { int num3 = untranslatedTexts[i].Split(new char[1] { '\n' }).Length; string text3 = string.Empty; for (int j = 0; j < num3; j++) { if (num2 >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text4 = array[num2++]; text3 += text4; if (j != num3 - 1) { text3 += "\n"; } } list.Add(text3); } if (num2 != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (Accept != null) { request.Headers[HttpRequestHeader.Accept] = Accept; } if (isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/"; } if (AcceptCharset != null) { request.Headers[HttpRequestHeader.AcceptCharset] = AcceptCharset; } } private void InspectResponse(XUnityWebResponse response) { CookieCollection newCookies = response.NewCookies; if (newCookies == null) { return; } foreach (Cookie item in newCookies) { item.Domain = ".googleapis.com"; } _cookieContainer.Add(newCookies); } public IEnumerator SetupTKK() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); yield break; } InspectResponse(response); try { string data = response.Data; bool flag = false; string[] array = new string[2] { "tkk:'", "TKK='" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("'", num2); string[] array2 = data.Substring(num2, num3 - num2).Split(new char[1] { '.' }); if (array2.Length == 2) { m = long.Parse(array2[0]); s = long.Parse(array2[1]); flag = true; break; } } } if (!flag) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate TKK. Could not locate TKK value. Using fallback TKK values instead."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead."); } } private long Vi(long r, string o) { for (int i = 0; i < o.Length; i += 3) { long num = o[i + 2]; num = ((num >= 97) ? (num - 87) : (num - 48)); num = (('+' == o[i + 1]) ? (r >> (int)num) : (r << (int)num)); r = (('+' == o[i]) ? ((r + num) & 0xFFFFFFFFu) : (r ^ num)); } return r; } private string Tk(string r) { List<long> list = new List<long>(); for (int i = 0; i < r.Length; i++) { long num = r[i]; if (128 > num) { list.Add(num); continue; } if (2048 > num) { list.Add((num >> 6) | 0xC0); } else if (55296 == (0xFC00 & num) && i + 1 < r.Length && 56320 == (0xFC00 & r[i + 1])) { num = 65536 + ((0x3FF & num) << 10) + (0x3FF & r[++i]); list.Add((num >> 18) | 0xF0); list.Add(((num >> 12) & 0x3F) | 0x80); } else { list.Add((num >> 12) | 0xE0); list.Add(((num >> 6) & 0x3F) | 0x80); } list.Add((0x3F & num) | 0x80); } long num2 = m; for (int j = 0; j < list.Count; j++) { num2 += list[j]; num2 = Vi(num2, "+-a^+6"); } num2 = Vi(num2, "+-3^+b+-f"); num2 ^= s; if (0 > num2) { num2 = (0x7FFFFFFF & num2) + 2147483648u; } num2 %= 1000000; return num2.ToString(CultureInfo.InvariantCulture) + "." + (num2 ^ m).ToString(CultureInfo.InvariantCulture); } } public class GoogleTranslateEndpointV2 : HttpEndpoint { private static readonly char[] WordSplitters = new char[3] { ' ', '\r', '\n' }; private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string DefaultUserBackend = "https://translate.google.com"; private static readonly string TranslationPostTemplate = "[[[\"{0}\",\"[[\\\"{1}\\\",\\\"{2}\\\",\\\"{3}\\\",true],[null]]\",null,\"generic\"]]]"; private static readonly string HttpsServicePointTranslateTemplateUrl = "/_/TranslateWebserverUi/data/batchexecute"; private static readonly Random RandomNumbers = new Random(); private static readonly string[] AcceptLanguages = new string[4] { null, "en-US,en;q=0.9", "en-US", "en" }; private static readonly string AcceptLanguage = AcceptLanguages[RandomNumbers.Next(AcceptLanguages.Length)]; private string _selectedUserBackend; private string _httpsServicePointTranslateTemplateUrl; private CookieContainer _cookieContainer; private bool _hasSetup; private long _FSID = LongRandom(long.MinValue, long.MaxValue, RandomNumbers); private int _translationCount; private int _resetAfter = RandomNumbers.Next(75, 125); private string _translateRpcId; private string _version; private bool _useSimplestSuggestion; private long _reqId; public override string Id => "GoogleTranslateV2"; public override string FriendlyName => "Google! Translate (v2)"; public override int MaxTranslationsPerRequest => 10; public GoogleTranslateEndpointV2() { _cookieContainer = new CookieContainer(); } private static long LongRandom(long min, long max, Random rand) { byte[] array = new byte[8]; rand.NextBytes(array); return Math.Abs(BitConverter.ToInt64(array, 0) % (max - min)) + min; } private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) string orCreateSetting = context.GetOrCreateSetting<string>("GoogleV2", "ServiceUrl"); if (!StringExtensions.IsNullOrWhiteSpace(orCreateSetting)) { _selectedUserBackend = orCreateSetting; _httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl; XuaLogger.AutoTranslator.Info("The default backend for google translate was overwritten."); } else { _selectedUserBackend = DefaultUserBackend; _httpsServicePointTranslateTemplateUrl = _selectedUserBackend + HttpsServicePointTranslateTemplateUrl; } _translateRpcId = context.GetOrCreateSetting<string>("GoogleV2", "RPCID", "MkEWBc"); _version = context.GetOrCreateSetting<string>("GoogleV2", "VERSION", "boq_translate-webserver_20210323.10_p0"); _useSimplestSuggestion = context.GetOrCreateSetting<bool>("GoogleV2", "UseSimplest", false); context.DisableCertificateChecksFor(new string[2] { new Uri(_selectedUserBackend).Host, new Uri(_selectedUserBackend).Host }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (!_hasSetup || _translationCount % _resetAfter == 0) { _resetAfter = RandomNumbers.Next(75, 125); _translationCount = 1; _reqId = RandomNumbers.Next(0, 100000); _hasSetup = true; IEnumerator enumerator = SetupFSID(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown _translationCount++; string text = JsonHelper.Escape(JsonHelper.Escape(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts))); string text2 = string.Join("&", "rpcids=" + _translateRpcId, "f.sid=" + _FSID.ToString(CultureInfo.InvariantCulture), "bl=" + Uri.EscapeDataString(_version), "hl=en-US", "soc-app=1", "soc-platform=1", "soc-device=1", "_reqid=" + _reqId.ToString(CultureInfo.InvariantCulture), "rt=c"); string text3 = "f.req=" + Uri.EscapeDataString(string.Format(TranslationPostTemplate, _translateRpcId, text, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage))) + "&"; string text4 = _httpsServicePointTranslateTemplateUrl + "?" + text2; XUnityWebRequest val = new XUnityWebRequest("POST", text4, text3); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: true); _reqId += 100000L; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) string data = ((IHttpResponseInspectionContext)context).Response.Data; data = data.Substring(6); string text = data.Substring(0, data.IndexOf("\n")); int length = int.Parse(text, CultureInfo.InvariantCulture); data = data.Substring(text.Length, length); string text2 = ((object)((JSONNode)((JSONNode)JSON.Parse(data).AsArray)[0].AsArray)[2]).ToString(); string text3 = JsonHelper.Unescape(text2.Substring(1, text2.Length - 2)); JSONNode obj = ((JSONNode)((JSONNode)((JSONNode)((JSONNode)JSON.Parse(text3).AsArray)[1].AsArray)[0].AsArray)[0].AsArray)[5]; StringBuilder stringBuilder = new StringBuilder(text3.Length); Enumerator enumerator = ((JSONNode)obj.AsArray).GetEnumerator(); while (((Enumerator)(ref enumerator)).MoveNext()) { JSONArray asArray = JSONNode.op_Implicit(((Enumerator)(ref enumerator)).Current).AsArray; string text4 = ((object)((JSONNode)asArray)[0]).ToString(); text4 = JsonHelper.Unescape(text4.Substring(1, text4.Length - 2)); if (StringExtensions.IsNullOrWhiteSpace(text4)) { continue; } if (_useSimplestSuggestion && ((JSONNode)asArray).Count > 1) { JSONNode obj2 = ((JSONNode)asArray)[1]; JSONArray val = ((obj2 != null) ? obj2.AsArray : null); if ((JSONNode)(object)val != (object)null) { HashSet<string> hashSet = new HashSet<string>(); hashSet.Add(text4); for (int i = 0; i < ((JSONNode)val).Count; i++) { string text5 = ((object)((JSONNode)val)[i]).ToString(); text5 = JsonHelper.Unescape(text5.Substring(1, text5.Length - 2)); hashSet.Add(text5); } if (hashSet.Count > 1) { XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Primary translation is '" + text4 + "', but found multiple suggestion:"); foreach (string item in hashSet) { XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: " + item); } int wordsInPrimary = text4.Split(WordSplitters).Length; text4 = (from x in hashSet where x.Split(WordSplitters).Length < wordsInPrimary orderby x.Split(WordSplitters).Length select x).FirstOrDefault() ?? text4; XuaLogger.AutoTranslator.Debug("[GoogleTranslateV2]: Selecting translation: " + text4); } } } if (!StringBuilderExtensions.EndsWithWhitespaceOrNewline(stringBuilder)) { stringBuilder.Append('\n'); } stringBuilder.Append(text4); } string text6 = stringBuilder.ToString(); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text6); return; } string[] array = text6.Split(new char[1] { '\n' }); List<string> list = new List<string>(); int num = 0; string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; for (int j = 0; j < untranslatedTexts.Length; j++) { int num2 = untranslatedTexts[j].Split(new char[1] { '\n' }).Length; string text7 = string.Empty; for (int k = 0; k < num2; k++) { if (num >= array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } string text8 = array[num++]; text7 += text8; if (k != num2 - 1) { text7 += "\n"; } } list.Add(text7); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Batch operation received incorrect number of translations."); } context.Complete(list.ToArray()); } private XUnityWebRequest CreateWebSiteRequest() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(_selectedUserBackend); val.Cookies = _cookieContainer; AddHeaders(val, isTranslationRequest: false); return val; } private void AddHeaders(XUnityWebRequest request, bool isTranslationRequest) { request.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); if (AcceptLanguage != null) { request.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage; } if (isTranslationRequest) { request.Headers[HttpRequestHeader.Referer] = _selectedUserBackend + "/"; request.Headers["X-Same-Domain"] = "1"; request.Headers["DNT"] = "1"; request.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded;charset=UTF-8"; request.Headers[HttpRequestHeader.Accept] = "*/*"; request.Headers["Origin"] = _selectedUserBackend; } else { request.Headers["Upgrade-Insecure-Requests"] = "1"; } } public IEnumerator SetupFSID() { _cookieContainer = new CookieContainer(); XUnityWebResponse response; try { XUnityWebClient val = new XUnityWebClient(); XUnityWebRequest val2 = CreateWebSiteRequest(); response = val.Send(val2); } catch (Exception ex) { XuaLogger.AutoTranslator.Warn(ex, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } IEnumerator iterator = ((CustomYieldInstructionShim)response).GetSupportedEnumerator(); while (iterator.MoveNext()) { yield return iterator.Current; } if (((CustomYieldInstructionShim)response).IsTimedOut) { XuaLogger.AutoTranslator.Warn("A timeout error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } if (response.Error != null) { XuaLogger.AutoTranslator.Warn(response.Error, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } if (response.Data == null) { XuaLogger.AutoTranslator.Warn((Exception)null, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); yield break; } try { string data = response.Data; bool flag = false; string[] array = new string[1] { "FdrFJe\":\"" }; foreach (string text in array) { int num = data.IndexOf(text); if (num > -1) { int num2 = num + text.Length; int num3 = data.IndexOf("\"", num2); string s = data.Substring(num2, num3 - num2); _FSID = long.Parse(s, CultureInfo.InvariantCulture); flag = true; break; } } if (!flag) { XuaLogger.AutoTranslator.Warn("An error occurred while setting up GoogleTranslate FSID. Could not locate FSID value. Using random instead."); } } catch (Exception ex2) { XuaLogger.AutoTranslator.Warn(ex2, "An error occurred while setting up GoogleTranslate FSID. Using random instead."); } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateCompat.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslateCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateCompat")] [assembly: AssemblyTitle("GoogleTranslateCompat")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateCompat; internal class GoogleTranslateCompatEndpoint : ExtProtocolEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "auto", "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; public override string Id => "GoogleTranslateCompat"; public override string FriendlyName => "Google! Translate (Compat)"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) ((ExtProtocolEndpoint)this).Initialize(context); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes("GoogleTranslateCompat.ExtProtocol.GoogleTranslateCompatTranslate, GoogleTranslateCompat.ExtProtocol")); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/GoogleTranslateLegitimate.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("GoogleTranslateLegitimate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GoogleTranslateLegitimate")] [assembly: AssemblyTitle("GoogleTranslateLegitimate")] [assembly: AssemblyVersion("1.0.0.0")] namespace GoogleTranslateLegitimate; internal class GoogleTranslateLegitimateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh", "zh-Hans", "zh-Hant", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu" }; private static readonly string HttpsServiceUrl = "https://translation.googleapis.com/language/translate/v2"; private string _key; public override string Id => "GoogleTranslateLegitimate"; public override string FriendlyName => "Google! Translate (Authenticated)"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("GoogleLegitimate", "GoogleAPIKey", ""); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The GoogleTranslateLegitimate endpoint requires an API key which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "translation.googleapis.com" }); if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(HttpsServiceUrl); stringBuilder.Append("?key=").Append(Uri.EscapeDataString(_key)); stringBuilder.Append("&source=").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage)); stringBuilder.Append("&target=").Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string stringToEscape = ((ITranslationContextBase)context).UntranslatedTexts[i]; stringBuilder.Append("&q=").Append(Uri.EscapeDataString(stringToEscape)); } XUnityWebRequest val = new XUnityWebRequest("POST", stringBuilder.ToString()); context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONArray asArray = ((JSONNode)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["data"].AsObject)["translations"].AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translatedText"]).ToString(); string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/LecPowerTranslator15.dll
Decompiled a year agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Microsoft.Win32; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.ExtProtocol; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("LecPowerTranslator15")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LecPowerTranslator15")] [assembly: AssemblyTitle("LecPowerTranslator15")] [assembly: AssemblyVersion("1.0.0.0")] namespace LecPowerTranslator15; internal class LecPowerTranslator15Endpoint : ExtProtocolEndpoint { public override string Id => "LecPowerTranslator15"; public override string FriendlyName => "LEC Power Translator 15"; public override int MaxConcurrency => 1; public override int MaxTranslationsPerRequest => 50; public override void Initialize(IInitializationContext context) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) string defaultInstallationPath = GetDefaultInstallationPath(); string text = context.GetOrCreateSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath); if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(defaultInstallationPath)) { context.SetSetting<string>("LecPowerTranslator15", "InstallationPath", defaultInstallationPath); text = defaultInstallationPath; } if (string.IsNullOrEmpty(text)) { throw new EndpointInitializationException("The LecPowerTranslator15 requires the path to the installation folder."); } context.DisableSpamChecks(); string text2 = Path.Combine(context.TranslatorDirectory, Path.Combine("FullNET", "Lec.ExtProtocol.exe")); if (!File.Exists(text2)) { throw new EndpointInitializationException("Could not find any executable at '" + text2 + "'"); } ((ExtProtocolEndpoint)this).ExecutablePath = text2; ((ExtProtocolEndpoint)this).Arguments = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); if (context.SourceLanguage != "ja") { throw new EndpointInitializationException("Current implementation only supports japanese-to-english."); } if (context.DestinationLanguage != "en") { throw new EndpointInitializationException("Current implementation only supports japanese-to-english."); } } public static string GetDefaultInstallationPath() { try { string text = GetInstallationPathFromRegistry(); if (!string.IsNullOrEmpty(text)) { text = new DirectoryInfo(text).Parent.FullName; } return text ?? string.Empty; } catch { return string.Empty; } } public static string GetInstallationPathFromRegistry() { try { if (IntPtr.Size == 8) { return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null); } return (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\LogoMedia\\LEC Power Translator 15\\Configuration", "ApplicationPath", null); } catch { return null; } } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/LingoCloudTranslate.dll
Decompiled a year agousing System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("LingoCloudTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LingoCloudTranslate")] [assembly: AssemblyTitle("LingoCloudTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace LingoCloudTranslate; internal class LingoCloudTranslateEndpoint : HttpEndpoint { private static readonly Dictionary<string, string> SupportedLanguages = new Dictionary<string, string> { { "en", "en" }, { "ja", "ja" }, { "jp", "ja" }, { "zh", "zh" }, { "zh-Hans", "zh" }, { "zh-CN", "zh" }, { "zh-Hant", "zh" }, { "zh-TW", "zh" } }; private static readonly string HttpServicePointTemplateUrl = "https://api.interpreter.caiyunai.com/v1/translator"; public string _token; public override string Id => "LingoCloudTranslate"; public override string FriendlyName => "CaiYun Translator"; private string FixLanguage(string lang) { if (SupportedLanguages.TryGetValue(lang, out var value)) { return value; } return lang; } public override void Initialize(IInitializationContext context) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) _token = context.GetOrCreateSetting<string>("LingoCloud", "LingoCloudToken", ""); if (string.IsNullOrEmpty(_token)) { throw new EndpointInitializationException("The LingoCloudTranslate endpoint requires an App Id which has not been provided."); } context.DisableCertificateChecksFor(new string[1] { "api.interpreter.caiyunai.com" }); if (!SupportedLanguages.ContainsKey(context.SourceLanguage)) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.ContainsKey(context.DestinationLanguage)) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown JSONObject val = new JSONObject(); string[] untranslatedTexts = ((ITranslationContextBase)context).UntranslatedTexts; foreach (string text in untranslatedTexts) { ((JSONNode)val)["source"].Add(JSONNode.op_Implicit(text)); } ((JSONNode)val)["trans_type"] = JSONNode.op_Implicit("auto2" + FixLanguage(((ITranslationContextBase)context).DestinationLanguage)); ((JSONNode)val)["request_id"] = JSONNode.op_Implicit("demo"); ((JSONNode)val)["detect"] = JSONNode.op_Implicit("true"); string text2 = ((object)val).ToString(); XUnityWebRequest val2 = new XUnityWebRequest("POST", HttpServicePointTemplateUrl, text2); val2.Headers[HttpRequestHeader.ContentType] = "application/json"; val2.Headers["X-Authorization"] = "token " + _token; context.Complete(val2); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["target"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(2, text.Length - 4)); context.Complete(text2); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/PapagoTranslate.dll
Decompiled a year agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core; using XUnity.AutoTranslator.Plugin.Core.Constants; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.Common.Logging; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("PapagoTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PapagoTranslate")] [assembly: AssemblyTitle("PapagoTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace PapagoTranslate; public class PapagoTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "en", "ko", "zh-CN", "zh-TW", "es", "fr", "ru", "vi", "th", "id", "de", "ja", "hi", "pt" }; private static readonly HashSet<string> SMTLanguages = new HashSet<string> { "hi", "pt" }; private static readonly string UrlBase = "https://papago.naver.com"; private static readonly string UrlN2MT = "/apis/n2mt/translate"; private static readonly string UrlNSMT = "/apis/nsmt/translate"; private static readonly string FormUrlEncodedTemplate = "deviceId={0}&locale=en&dict=false&honorific=false&instant=true&source={1}&target={2}&text={3}"; private static readonly Random RandomNumbers = new Random(); private static readonly Guid UUID = Guid.NewGuid(); private static readonly Regex PatternSource = new Regex("/vendors~main[^\"]+", RegexOptions.Singleline); private static readonly Regex PatternVersion = new Regex("v\\d\\.\\d\\.\\d_[^\"]+", RegexOptions.Singleline); private string _version; private bool _isSMT; private int _translationCount; private int _resetAfter; public override string Id => "PapagoTranslate"; public override string FriendlyName => "Papago Translator"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-Hans": case "zh": return "zh-CN"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) context.DisableCertificateChecksFor(new string[1] { "papago.naver.com" }); string text = FixLanguage(context.SourceLanguage); string text2 = FixLanguage(context.DestinationLanguage); _isSMT = SMTLanguages.Contains(text) || SMTLanguages.Contains(text2); if (!SupportedLanguages.Contains(text2)) { throw new EndpointInitializationException("The language '" + context.DestinationLanguage + "' is not supported by Papago Translate."); } if (_isSMT && text != "en" && text2 != "en") { throw new EndpointInitializationException("Translation from '" + context.SourceLanguage + "' to '" + context.DestinationLanguage + "' is not supported by Papago Translate."); } } public override IEnumerator OnBeforeTranslate(IHttpTranslationContext context) { if (_resetAfter == 0 || _translationCount % _resetAfter == 0) { _translationCount = 1; _resetAfter = RandomNumbers.Next(150, 200); IEnumerator enumerator = SetupVersion(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown string text = Uri.EscapeDataString(string.Join("\n", ((ITranslationContextBase)context).UntranslatedTexts)); XUnityWebRequest val = new XUnityWebRequest("POST", UrlBase + (_isSMT ? UrlNSMT : UrlN2MT), string.Format(FormUrlEncodedTemplate, UUID, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), text)); DateTime utcNow = DateTime.UtcNow; DateTime minValue = DateTime.MinValue; double num = Math.Truncate(utcNow.Subtract(minValue.AddYears(1969)).TotalMilliseconds); byte[] bytes = Encoding.UTF8.GetBytes(_version); byte[] bytes2 = Encoding.UTF8.GetBytes($"{UUID}\n{val.Address}\n{num}"); string arg = Convert.ToBase64String(new HMACMD5(bytes).ComputeHash(bytes2)); val.Headers[HttpRequestHeader.UserAgent] = (string.IsNullOrEmpty(AutoTranslatorSettings.UserAgent) ? UserAgents.Chrome_Win10_Latest : AutoTranslatorSettings.UserAgent); val.Headers["Authorization"] = $"PPG {UUID}:{arg}"; val.Headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; val.Headers["Timestamp"] = num.ToString(); context.Complete(val); _translationCount++; } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { string text = ((object)((JSONNode)JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data).AsObject)["translatedText"]).ToString(); string text2 = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); if (((ITranslationContextBase)context).UntranslatedTexts.Length == 1) { context.Complete(text2); return; } string[] array = text2.Split(new char[1] { '\n' }); string[] array2 = new string[((ITranslationContextBase)context).UntranslatedTexts.Length]; int num = 0; for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string[] array3 = ((ITranslationContextBase)context).UntranslatedTexts[i].Split(new char[1] { '\n' }); StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < array3.Length; j++) { string value = array[num++]; if (array3.Length - 1 == j) { stringBuilder.Append(value); } else { stringBuilder.AppendLine(value); } } array2[i] = stringBuilder.ToString(); } if (num != array.Length) { ((ITranslationContextBase)context).Fail("Received invalid number of translations in batch."); } context.Complete(array2); } private IEnumerator SetupVersion() { XUnityWebClient client = new XUnityWebClient(); XUnityWebResponse response2 = client.Send(new XUnityWebRequest(UrlBase)); IEnumerator iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator(); while (iterator2.MoveNext()) { yield return iterator2.Current; } Match match = PatternSource.Match(response2.Data); if (!match.Success) { XuaLogger.AutoTranslator.Warn("Could not parse papago page"); yield break; } string value = match.Value; response2 = client.Send(new XUnityWebRequest(UrlBase + value)); iterator2 = ((CustomYieldInstructionShim)response2).GetSupportedEnumerator(); while (iterator2.MoveNext()) { yield return iterator2.Current; } Match match2 = PatternVersion.Match(response2.Data); if (!match2.Success) { XuaLogger.AutoTranslator.Warn("Could not parse papago version"); yield break; } XuaLogger.AutoTranslator.Debug("Current papago version is " + match2.Value); _version = match2.Value; } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/WatsonTranslate.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Www; using XUnity.AutoTranslator.Plugin.Core.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("WatsonTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("WatsonTranslate")] [assembly: AssemblyTitle("WatsonTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace WatsonTranslate; internal class WatsonTranslateEndpoint : WwwEndpoint { private static readonly HashSet<string> SupportedLanguagePairs = new HashSet<string> { "ar-en", "ca-es", "zh-en", "zh-TW-en", "cs-en", "da-en", "nl-en", "en-ar", "en-cs", "en-da", "en-de", "en-es", "en-fi", "en-fr", "en-hi", "en-it", "en-ja", "en-ko", "en-nb", "en-nl", "en-pl", "en-pt", "en-ru", "en-sv", "en-tr", "en-zh", "en-zh-TW", "fi-en", "fr-de", "fr-en", "fr-es", "de-en", "de-fr", "de-it", "hi-en", "hu-en", "it-de", "it-en", "ja-en", "ko-en", "nb-en", "pl-en", "pt-en", "ru-en", "es-ca", "es-en", "es-fr", "sv-en", "tr-en" }; private string _fullUrl; private string _url; private string _key; public override string Id => "WatsonTranslate"; public override string FriendlyName => "Watson Language Translator"; public override int MaxTranslationsPerRequest => 10; private string FixLanguage(string lang) { switch (lang) { case "zh-CN": case "zh-Hans": return "zh"; case "zh-Hant": return "zh-TW"; default: return lang; } } public override void Initialize(IInitializationContext context) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) _url = context.GetOrCreateSetting<string>("Watson", "Url", ""); _key = context.GetOrCreateSetting<string>("Watson", "Key", ""); if (string.IsNullOrEmpty(_url)) { throw new EndpointInitializationException("The WatsonTranslate endpoint requires a url which has not been provided."); } if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The WatsonTranslate endpoint requires a key which has not been provided."); } _fullUrl = _url.TrimEnd(new char[1] { '/' }) + "/v3/translate?version=2018-05-01"; string text = FixLanguage(context.SourceLanguage) + "-" + FixLanguage(context.DestinationLanguage); if (!SupportedLanguagePairs.Contains(text)) { throw new EndpointInitializationException("The language model '" + text + "' is not supported."); } } public override void OnCreateRequest(IWwwRequestCreationContext context) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{\"text\":["); for (int i = 0; i < ((ITranslationContextBase)context).UntranslatedTexts.Length; i++) { string value = JsonHelper.Escape(((ITranslationContextBase)context).UntranslatedTexts[i]); stringBuilder.Append("\"").Append(value).Append("\""); if (((ITranslationContextBase)context).UntranslatedTexts.Length - 1 != i) { stringBuilder.Append(","); } } stringBuilder.Append("],\"model_id\":\"").Append(FixLanguage(((ITranslationContextBase)context).SourceLanguage)).Append("-") .Append(FixLanguage(((ITranslationContextBase)context).DestinationLanguage)) .Append("\"}"); WwwRequestInfo val = new WwwRequestInfo(_fullUrl, stringBuilder.ToString()); val.Headers["Accept"] = "application/json"; val.Headers["Content-Type"] = "application/json"; val.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("apikey:" + _key)); context.Complete(val); } public override void OnExtractTranslation(IWwwTranslationExtractionContext context) { JSONArray asArray = ((JSONNode)JSON.Parse(context.ResponseData).AsObject)["translations"].AsArray; List<string> list = new List<string>(); for (int i = 0; i < ((JSONNode)asArray).Count; i++) { string text = ((object)((JSONNode)((JSONNode)asArray)[i].AsObject)["translation"]).ToString(); string item = JsonHelper.Unescape(text.Substring(1, text.Length - 2)); list.Add(item); } context.Complete(list.ToArray()); } }
BepInEx/plugins/XUnity.AutoTranslator/Translators/YandexTranslate.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Reflection; using System.Runtime.CompilerServices; using SimpleJSON; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("YandexTranslate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("YandexTranslate")] [assembly: AssemblyTitle("YandexTranslate")] [assembly: AssemblyVersion("1.0.0.0")] namespace YandexTranslate; internal class YandexTranslateEndpoint : HttpEndpoint { private static readonly HashSet<string> SupportedLanguages = new HashSet<string> { "az", "sq", "am", "en", "ar", "hy", "af", "eu", "ba", "be", "bn", "my", "bg", "bs", "cy", "hu", "vi", "ht", "gl", "nl", "mrj", "el", "ka", "gu", "da", "he", "yi", "id", "ga", "it", "is", "es", "kk", "kn", "ca", "ky", "zh", "ko", "xh", "km", "lo", "la", "lv", "lt", "lb", "mg", "ms", "ml", "mt", "mk", "mi", "mr", "mhr", "mn", "de", "ne", "no", "pa", "pap", "fa", "pl", "pt", "ro", "ru", "ceb", "sr", "si", "sk", "sl", "sw", "su", "tg", "th", "tl", "ta", "tt", "te", "tr", "udm", "uz", "uk", "ur", "fi", "fr", "hi", "hr", "cs", "sv", "gd", "et", "eo", "jv", "ja" }; private static readonly string HttpsServicePointTemplateUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={3}&text={2}&lang={0}-{1}&format=plain"; private string _key; public override string Id => "YandexTranslate"; public override string FriendlyName => "Yandex Translate"; private string FixLanguage(string lang) { if (lang == "zh-CN" || lang == "zh-Hans") { return "zh"; } return lang; } public override void Initialize(IInitializationContext context) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _key = context.GetOrCreateSetting<string>("Yandex", "YandexAPIKey", ""); context.DisableCertificateChecksFor(new string[1] { "translate.yandex.net" }); if (string.IsNullOrEmpty(_key)) { throw new EndpointInitializationException("The YandexTranslate endpoint requires an API key which has not been provided."); } if (!SupportedLanguages.Contains(FixLanguage(context.SourceLanguage))) { throw new EndpointInitializationException("The source language '" + context.SourceLanguage + "' is not supported."); } if (!SupportedLanguages.Contains(FixLanguage(context.DestinationLanguage))) { throw new EndpointInitializationException("The destination language '" + context.DestinationLanguage + "' is not supported."); } } public override void OnCreateRequest(IHttpRequestCreationContext context) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown XUnityWebRequest val = new XUnityWebRequest(string.Format(HttpsServicePointTemplateUrl, FixLanguage(((ITranslationContextBase)context).SourceLanguage), FixLanguage(((ITranslationContextBase)context).DestinationLanguage), Uri.EscapeDataString(((ITranslationContextBase)context).UntranslatedText), _key)); val.Headers[HttpRequestHeader.Accept] = "*/*"; val.Headers[HttpRequestHeader.AcceptCharset] = "UTF-8"; context.Complete(val); } public override void OnExtractTranslation(IHttpTranslationExtractionContext context) { JSONNode obj = JSON.Parse(((IHttpResponseInspectionContext)context).Response.Data); string text = ((object)((JSONNode)obj.AsObject)["code"]).ToString(); if (text != "200") { ((ITranslationContextBase)context).Fail("Received bad response code: " + text); } string text2 = ((object)((JSONNode)obj.AsObject)["text"]).ToString(); string text3 = JsonHelper.Unescape(text2.Substring(2, text2.Length - 4)); if (string.IsNullOrEmpty(text3)) { ((ITranslationContextBase)context).Fail("Received no translation."); } context.Complete(text3); } }
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.BepInEx.dll
Decompiled a year agousing System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using ExIni; using XUnity.AutoTranslator.Plugin.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("5.3.0.0")] [assembly: AssemblyInformationalVersion("5.3.0")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.BepInEx")] [assembly: AssemblyVersion("5.3.0.0")] namespace XUnity.AutoTranslator.Plugin.BepInEx; [BepInPlugin("gravydevsupreme.xunity.autotranslator", "XUnity Auto Translator", "5.3.0")] public class AutoTranslatorPlugin : BaseUnityPlugin, IPluginEnvironment { private IniFile _file; private string _configPath; public IniFile Preferences => _file ?? (_file = ReloadConfig()); public string ConfigPath { get; } public string TranslationPath { get; } public bool AllowDefaultInitializeHarmonyDetourBridge => false; public AutoTranslatorPlugin() { ConfigPath = Paths.ConfigPath; TranslationPath = Paths.BepInExRootPath; _configPath = Path.Combine(ConfigPath, "AutoTranslatorConfig.ini"); } public IniFile ReloadConfig() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(_configPath)) { return (IniFile)(((object)_file) ?? ((object)new IniFile())); } IniFile val = IniFile.FromFile(_configPath); if (_file == null) { return _file = val; } _file.Merge(val); return _file; } public void SaveConfig() { _file.Save(_configPath); } private void Awake() { PluginLoader.LoadWithConfig((IPluginEnvironment)(object)this); } }
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.Core.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Cache; using System.Net.Security; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using DynamicLinq; using ExIni; using Harmony; using ICSharpCode.SharpZipLib.Checksums; using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Encryption; using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip.Compression; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using UnityEngine; using UnityEngine.SceneManagement; using XUnity.AutoTranslator.Plugin.Core.AssetRedirection; using XUnity.AutoTranslator.Plugin.Core.Configuration; using XUnity.AutoTranslator.Plugin.Core.Debugging; using XUnity.AutoTranslator.Plugin.Core.Endpoints; using XUnity.AutoTranslator.Plugin.Core.Extensions; using XUnity.AutoTranslator.Plugin.Core.Fonts; using XUnity.AutoTranslator.Plugin.Core.Hooks; using XUnity.AutoTranslator.Plugin.Core.Hooks.NGUI; using XUnity.AutoTranslator.Plugin.Core.Hooks.TextMeshPro; using XUnity.AutoTranslator.Plugin.Core.Hooks.UGUI; using XUnity.AutoTranslator.Plugin.Core.Managed.Textures; using XUnity.AutoTranslator.Plugin.Core.Parsing; using XUnity.AutoTranslator.Plugin.Core.Properties; using XUnity.AutoTranslator.Plugin.Core.Shims; using XUnity.AutoTranslator.Plugin.Core.Text; using XUnity.AutoTranslator.Plugin.Core.Textures; using XUnity.AutoTranslator.Plugin.Core.UI; using XUnity.AutoTranslator.Plugin.Core.UIResize; using XUnity.AutoTranslator.Plugin.Core.Utilities; using XUnity.AutoTranslator.Plugin.Core.Web; using XUnity.AutoTranslator.Plugin.Core.Web.Internal; using XUnity.AutoTranslator.Plugin.ExtProtocol; using XUnity.AutoTranslator.Plugin.Utilities; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Harmony; using XUnity.Common.Logging; using XUnity.Common.MonoMod; using XUnity.Common.Utilities; using XUnity.ResourceRedirector; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.Core")] [assembly: AssemblyInformationalVersion("5.3.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyDescription("Main development dependency for XUnity Auto Translator.")] [assembly: AssemblyFileVersion("5.3.0.0")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: InternalsVisibleTo("XUnity.AutoTranslator.Plugin.Core.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("5.3.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DynamicLinq { internal static class DynamicQueryable { public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values) { return (IQueryable<T>)((IQueryable)source).Where(predicate, values); } public static IQueryable Where(this IQueryable source, string predicate, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } LambdaExpression expression = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Where", new Type[1] { source.ElementType }, source.Expression, Expression.Quote(expression))); } public static IQueryable Select(this IQueryable source, string selector, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, selector, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Select", new Type[2] { source.ElementType, lambdaExpression.Body.Type }, source.Expression, Expression.Quote(lambdaExpression))); } public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) { return (IQueryable<T>)((IQueryable)source).OrderBy(ordering, values); } public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (ordering == null) { throw new ArgumentNullException("ordering"); } ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(source.ElementType, "") }; IEnumerable<DynamicOrdering> enumerable = new ExpressionParser(parameters, ordering, values).ParseOrdering(); Expression expression = source.Expression; string text = "OrderBy"; string text2 = "OrderByDescending"; foreach (DynamicOrdering item in enumerable) { expression = Expression.Call(typeof(Queryable), item.Ascending ? text : text2, new Type[2] { source.ElementType, item.Selector.Type }, expression, Expression.Quote(Expression.Lambda(item.Selector, parameters))); text = "ThenBy"; text2 = "ThenByDescending"; } return source.Provider.CreateQuery(expression); } public static IQueryable Take(this IQueryable source, int count) { if (source == null) { throw new ArgumentNullException("source"); } return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Take", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count))); } public static IQueryable Skip(this IQueryable source, int count) { if (source == null) { throw new ArgumentNullException("source"); } return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Skip", new Type[1] { source.ElementType }, source.Expression, Expression.Constant(count))); } public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (elementSelector == null) { throw new ArgumentNullException("elementSelector"); } LambdaExpression lambdaExpression = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values); LambdaExpression lambdaExpression2 = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values); return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "GroupBy", new Type[3] { source.ElementType, lambdaExpression.Body.Type, lambdaExpression2.Body.Type }, source.Expression, Expression.Quote(lambdaExpression), Expression.Quote(lambdaExpression2))); } public static bool Any(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } return (bool)source.Provider.Execute(Expression.Call(typeof(Queryable), "Any", new Type[1] { source.ElementType }, source.Expression)); } public static int Count(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } return (int)source.Provider.Execute(Expression.Call(typeof(Queryable), "Count", new Type[1] { source.ElementType }, source.Expression)); } } internal abstract class DynamicClass { public override string ToString() { PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("{"); for (int i = 0; i < properties.Length; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(properties[i].Name); stringBuilder.Append("="); stringBuilder.Append(properties[i].GetValue(this, null)); } stringBuilder.Append("}"); return stringBuilder.ToString(); } } internal class DynamicProperty { private string name; private Type type; public string Name => name; public Type Type => type; public DynamicProperty(string name, Type type) { if (name == null) { throw new ArgumentNullException("name"); } if ((object)type == null) { throw new ArgumentNullException("type"); } this.name = name; this.type = type; } } internal static class DynamicExpression { public static Expression Parse(Type resultType, string expression, params object[] values) { return new ExpressionParser(null, expression, values).Parse(resultType); } public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values) { return ParseLambda(new ParameterExpression[1] { Expression.Parameter(itType, "") }, resultType, expression, values); } public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values) { return Expression.Lambda(new ExpressionParser(parameters, expression, values).Parse(resultType), parameters); } public static Expression<Func<T, S>> ParseLambda<T, S>(string expression, params object[] values) { return (Expression<Func<T, S>>)ParseLambda(typeof(T), typeof(S), expression, values); } public static Type CreateClass(params DynamicProperty[] properties) { throw new NotImplementedException(); } public static Type CreateClass(IEnumerable<DynamicProperty> properties) { throw new NotImplementedException(); } } internal class DynamicOrdering { public Expression Selector; public bool Ascending; } internal class Signature : IEquatable<Signature> { public DynamicProperty[] properties; public int hashCode; public Signature(IEnumerable<DynamicProperty> properties) { this.properties = properties.ToArray(); hashCode = 0; foreach (DynamicProperty property in properties) { hashCode ^= property.Name.GetHashCode() ^ property.Type.GetHashCode(); } } public override int GetHashCode() { return hashCode; } public override bool Equals(object obj) { if (!(obj is Signature)) { return false; } return Equals((Signature)obj); } public bool Equals(Signature other) { if (properties.Length != other.properties.Length) { return false; } for (int i = 0; i < properties.Length; i++) { if (properties[i].Name != other.properties[i].Name || (object)properties[i].Type != other.properties[i].Type) { return false; } } return true; } } internal sealed class ParseException : Exception { private int position; public int Position => position; public ParseException(string message, int position) : base(message) { this.position = position; } public override string ToString() { return $"{Message} (at index {position})"; } } internal class ExpressionParser { private struct Token { public TokenId id; public string text; public int pos; } private enum TokenId { Unknown, End, Identifier, StringLiteral, IntegerLiteral, RealLiteral, Exclamation, Percent, Amphersand, OpenParen, CloseParen, Asterisk, Plus, Comma, Minus, Dot, Slash, Colon, LessThan, Equal, GreaterThan, Question, OpenBracket, CloseBracket, Bar, ExclamationEqual, DoubleAmphersand, LessThanEqual, LessGreater, DoubleEqual, GreaterThanEqual, DoubleBar } private interface ILogicalSignatures { void F(bool x, bool y); void F(bool? x, bool? y); } private interface IArithmeticSignatures { void F(int x, int y); void F(uint x, uint y); void F(long x, long y); void F(ulong x, ulong y); void F(float x, float y); void F(double x, double y); void F(decimal x, decimal y); void F(int? x, int? y); void F(uint? x, uint? y); void F(long? x, long? y); void F(ulong? x, ulong? y); void F(float? x, float? y); void F(double? x, double? y); void F(decimal? x, decimal? y); } private interface IRelationalSignatures : IArithmeticSignatures { void F(string x, string y); void F(char x, char y); void F(DateTime x, DateTime y); void F(TimeSpan x, TimeSpan y); void F(char? x, char? y); void F(DateTime? x, DateTime? y); void F(TimeSpan? x, TimeSpan? y); } private interface IEqualitySignatures : IRelationalSignatures, IArithmeticSignatures { void F(bool x, bool y); void F(bool? x, bool? y); } private interface IAddSignatures : IArithmeticSignatures { void F(DateTime x, TimeSpan y); void F(TimeSpan x, TimeSpan y); void F(DateTime? x, TimeSpan? y); void F(TimeSpan? x, TimeSpan? y); } private interface ISubtractSignatures : IAddSignatures, IArithmeticSignatures { void F(DateTime x, DateTime y); void F(DateTime? x, DateTime? y); } private interface INegationSignatures { void F(int x); void F(long x); void F(float x); void F(double x); void F(decimal x); void F(int? x); void F(long? x); void F(float? x); void F(double? x); void F(decimal? x); } private interface INotSignatures { void F(bool x); void F(bool? x); } private interface IEnumerableSignatures { void Where(bool predicate); void Any(); void Any(bool predicate); void All(bool predicate); void Count(); void Count(bool predicate); void Min(object selector); void Max(object selector); void Sum(int selector); void Sum(int? selector); void Sum(long selector); void Sum(long? selector); void Sum(float selector); void Sum(float? selector); void Sum(double selector); void Sum(double? selector); void Sum(decimal selector); void Sum(decimal? selector); void Average(int selector); void Average(int? selector); void Average(long selector); void Average(long? selector); void Average(float selector); void Average(float? selector); void Average(double selector); void Average(double? selector); void Average(decimal selector); void Average(decimal? selector); } private class MethodData { public MethodBase MethodBase; public ParameterInfo[] Parameters; public Expression[] Args; } private static readonly Type[] predefinedTypes = new Type[20] { typeof(object), typeof(bool), typeof(char), typeof(string), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(DateTime), typeof(TimeSpan), typeof(Guid), typeof(Math), typeof(Convert) }; private static readonly Expression trueLiteral = Expression.Constant(true); private static readonly Expression falseLiteral = Expression.Constant(false); private static readonly Expression nullLiteral = Expression.Constant(null); private static readonly string keywordIt = "it"; private static readonly string keywordIif = "iif"; private static readonly string keywordNew = "new"; private static Dictionary<string, object> keywords; private Dictionary<string, object> symbols; private IDictionary<string, object> externals; private Dictionary<Expression, string> literals; private ParameterExpression it; private string text; private int textPos; private int textLen; private char ch; private Token token; public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values) { if (expression == null) { throw new ArgumentNullException("expression"); } if (keywords == null) { keywords = CreateKeywords(); } symbols = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); literals = new Dictionary<Expression, string>(); if (parameters != null) { ProcessParameters(parameters); } if (values != null) { ProcessValues(values); } text = expression; textLen = text.Length; SetTextPos(0); NextToken(); } private void ProcessParameters(ParameterExpression[] parameters) { foreach (ParameterExpression parameterExpression in parameters) { if (!string.IsNullOrEmpty(parameterExpression.Name)) { AddSymbol(parameterExpression.Name, parameterExpression); } } if (parameters.Length == 1 && string.IsNullOrEmpty(parameters[0].Name)) { it = parameters[0]; } } private void ProcessValues(object[] values) { for (int i = 0; i < values.Length; i++) { object obj = values[i]; if (i == values.Length - 1 && obj is IDictionary<string, object>) { externals = (IDictionary<string, object>)obj; } else { AddSymbol("@" + i.ToString(CultureInfo.InvariantCulture), obj); } } } private void AddSymbol(string name, object value) { if (symbols.ContainsKey(name)) { throw ParseError("The identifier '{0}' was defined more than once", name); } symbols.Add(name, value); } public Expression Parse(Type resultType) { int pos = token.pos; Expression expression = ParseExpression(); if ((object)resultType != null && (expression = PromoteExpression(expression, resultType, exact: true)) == null) { throw ParseError(pos, "Expression of type '{0}' expected", GetTypeName(resultType)); } ValidateToken(TokenId.End, "Syntax error"); return expression; } public IEnumerable<DynamicOrdering> ParseOrdering() { List<DynamicOrdering> list = new List<DynamicOrdering>(); while (true) { Expression selector = ParseExpression(); bool ascending = true; if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending")) { NextToken(); } else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending")) { NextToken(); ascending = false; } list.Add(new DynamicOrdering { Selector = selector, Ascending = ascending }); if (token.id != TokenId.Comma) { break; } NextToken(); } ValidateToken(TokenId.End, "Syntax error"); return list; } private Expression ParseExpression() { int pos = token.pos; Expression expression = ParseLogicalOr(); if (token.id == TokenId.Question) { NextToken(); Expression expr = ParseExpression(); ValidateToken(TokenId.Colon, "':' expected"); NextToken(); Expression expr2 = ParseExpression(); expression = GenerateConditional(expression, expr, expr2, pos); } return expression; } private Expression ParseLogicalOr() { Expression left = ParseLogicalAnd(); while (this.token.id == TokenId.DoubleBar || TokenIdentifierIs("or")) { Token token = this.token; NextToken(); Expression right = ParseLogicalAnd(); CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos); left = Expression.OrElse(left, right); } return left; } private Expression ParseLogicalAnd() { Expression left = ParseComparison(); while (this.token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and")) { Token token = this.token; NextToken(); Expression right = ParseComparison(); CheckAndPromoteOperands(typeof(ILogicalSignatures), token.text, ref left, ref right, token.pos); left = Expression.AndAlso(left, right); } return left; } private Expression ParseComparison() { Expression left = ParseAdditive(); while (this.token.id == TokenId.Equal || this.token.id == TokenId.DoubleEqual || this.token.id == TokenId.ExclamationEqual || this.token.id == TokenId.LessGreater || this.token.id == TokenId.GreaterThan || this.token.id == TokenId.GreaterThanEqual || this.token.id == TokenId.LessThan || this.token.id == TokenId.LessThanEqual) { Token token = this.token; NextToken(); Expression right = ParseAdditive(); bool flag = token.id == TokenId.Equal || token.id == TokenId.DoubleEqual || token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater; if (flag && !left.Type.IsValueType && !right.Type.IsValueType) { if ((object)left.Type != right.Type) { if (left.Type.IsAssignableFrom(right.Type)) { right = Expression.Convert(right, left.Type); } else { if (!right.Type.IsAssignableFrom(left.Type)) { throw IncompatibleOperandsError(token.text, left, right, token.pos); } left = Expression.Convert(left, right.Type); } } } else if (IsEnumType(left.Type) || IsEnumType(right.Type)) { if ((object)left.Type != right.Type) { Expression expression; if ((expression = PromoteExpression(right, left.Type, exact: true)) != null) { right = expression; } else { if ((expression = PromoteExpression(left, right.Type, exact: true)) == null) { throw IncompatibleOperandsError(token.text, left, right, token.pos); } left = expression; } } } else { CheckAndPromoteOperands(flag ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), token.text, ref left, ref right, token.pos); } switch (token.id) { case TokenId.Equal: case TokenId.DoubleEqual: left = GenerateEqual(left, right); break; case TokenId.ExclamationEqual: case TokenId.LessGreater: left = GenerateNotEqual(left, right); break; case TokenId.GreaterThan: left = GenerateGreaterThan(left, right); break; case TokenId.GreaterThanEqual: left = GenerateGreaterThanEqual(left, right); break; case TokenId.LessThan: left = GenerateLessThan(left, right); break; case TokenId.LessThanEqual: left = GenerateLessThanEqual(left, right); break; } } return left; } private Expression ParseAdditive() { Expression left = ParseMultiplicative(); while (this.token.id == TokenId.Plus || this.token.id == TokenId.Minus || this.token.id == TokenId.Amphersand) { Token token = this.token; NextToken(); Expression right = ParseMultiplicative(); TokenId id = token.id; if (id != TokenId.Amphersand) { if (id != TokenId.Plus) { if (id == TokenId.Minus) { CheckAndPromoteOperands(typeof(ISubtractSignatures), token.text, ref left, ref right, token.pos); left = GenerateSubtract(left, right); } continue; } if ((object)left.Type != typeof(string) && (object)right.Type != typeof(string)) { CheckAndPromoteOperands(typeof(IAddSignatures), token.text, ref left, ref right, token.pos); left = GenerateAdd(left, right); continue; } } left = GenerateStringConcat(left, right); } return left; } private Expression ParseMultiplicative() { Expression left = ParseUnary(); while (this.token.id == TokenId.Asterisk || this.token.id == TokenId.Slash || this.token.id == TokenId.Percent || TokenIdentifierIs("mod")) { Token token = this.token; NextToken(); Expression right = ParseUnary(); CheckAndPromoteOperands(typeof(IArithmeticSignatures), token.text, ref left, ref right, token.pos); switch (token.id) { case TokenId.Asterisk: left = Expression.Multiply(left, right); break; case TokenId.Slash: left = Expression.Divide(left, right); break; case TokenId.Identifier: case TokenId.Percent: left = Expression.Modulo(left, right); break; } } return left; } private Expression ParseUnary() { if (this.token.id == TokenId.Minus || this.token.id == TokenId.Exclamation || TokenIdentifierIs("not")) { Token token = this.token; NextToken(); if (token.id == TokenId.Minus && (this.token.id == TokenId.IntegerLiteral || this.token.id == TokenId.RealLiteral)) { this.token.text = "-" + this.token.text; this.token.pos = token.pos; return ParsePrimary(); } Expression expr = ParseUnary(); if (token.id == TokenId.Minus) { CheckAndPromoteOperand(typeof(INegationSignatures), token.text, ref expr, token.pos); return Expression.Negate(expr); } CheckAndPromoteOperand(typeof(INotSignatures), token.text, ref expr, token.pos); return Expression.Not(expr); } return ParsePrimary(); } private Expression ParsePrimary() { Expression expression = ParsePrimaryStart(); while (true) { if (token.id == TokenId.Dot) { NextToken(); expression = ParseMemberAccess(null, expression); continue; } if (token.id != TokenId.OpenBracket) { break; } expression = ParseElementAccess(expression); } return expression; } private Expression ParsePrimaryStart() { return token.id switch { TokenId.Identifier => ParseIdentifier(), TokenId.StringLiteral => ParseStringLiteral(), TokenId.IntegerLiteral => ParseIntegerLiteral(), TokenId.RealLiteral => ParseRealLiteral(), TokenId.OpenParen => ParseParenExpression(), _ => throw ParseError("Expression expected"), }; } private Expression ParseStringLiteral() { ValidateToken(TokenId.StringLiteral); char c = token.text[0]; string text = token.text.Substring(1, token.text.Length - 2); int startIndex = 0; while (true) { int num = text.IndexOf(c, startIndex); if (num < 0) { break; } text = text.Remove(num, 1); startIndex = num + 1; } if (c == '\'') { if (text.Length != 1) { throw ParseError("Character literal must contain exactly one character"); } NextToken(); return CreateLiteral(text[0], text); } NextToken(); return CreateLiteral(text, text); } private Expression ParseIntegerLiteral() { ValidateToken(TokenId.IntegerLiteral); string text = token.text; if (text[0] != '-') { if (!ulong.TryParse(text, out var result)) { throw ParseError("Invalid integer literal '{0}'", text); } NextToken(); if (result <= int.MaxValue) { return CreateLiteral((int)result, text); } if (result <= uint.MaxValue) { return CreateLiteral((uint)result, text); } if (result <= long.MaxValue) { return CreateLiteral((long)result, text); } return CreateLiteral(result, text); } if (!long.TryParse(text, out var result2)) { throw ParseError("Invalid integer literal '{0}'", text); } NextToken(); if (result2 >= int.MinValue && result2 <= int.MaxValue) { return CreateLiteral((int)result2, text); } return CreateLiteral(result2, text); } private Expression ParseRealLiteral() { ValidateToken(TokenId.RealLiteral); string text = token.text; object obj = null; char c = text[text.Length - 1]; double result2; if (c == 'F' || c == 'f') { if (float.TryParse(text.Substring(0, text.Length - 1), out var result)) { obj = result; } } else if (double.TryParse(text, out result2)) { obj = result2; } if (obj == null) { throw ParseError("Invalid real literal '{0}'", text); } NextToken(); return CreateLiteral(obj, text); } private Expression CreateLiteral(object value, string text) { ConstantExpression constantExpression = Expression.Constant(value); literals.Add(constantExpression, text); return constantExpression; } private Expression ParseParenExpression() { ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); Expression result = ParseExpression(); ValidateToken(TokenId.CloseParen, "')' or operator expected"); NextToken(); return result; } private Expression ParseIdentifier() { ValidateToken(TokenId.Identifier); if (keywords.TryGetValue(token.text, out var value)) { if (value is Type) { return ParseTypeAccess((Type)value); } if (value == keywordIt) { return ParseIt(); } if (value == keywordIif) { return ParseIif(); } if (value == keywordNew) { return ParseNew(); } NextToken(); return (Expression)value; } if (symbols.TryGetValue(token.text, out value) || (externals != null && externals.TryGetValue(token.text, out value))) { Expression expression = value as Expression; if (expression == null) { expression = Expression.Constant(value); } else if (expression is LambdaExpression lambda) { return ParseLambdaInvocation(lambda); } NextToken(); return expression; } if (it != null) { return ParseMemberAccess(null, it); } throw ParseError("Unknown identifier '{0}'", token.text); } private Expression ParseIt() { if (it == null) { throw ParseError("No 'it' is in scope"); } NextToken(); return it; } private Expression ParseIif() { int pos = token.pos; NextToken(); Expression[] array = ParseArgumentList(); if (array.Length != 3) { throw ParseError(pos, "The 'iif' function requires three arguments"); } return GenerateConditional(array[0], array[1], array[2], pos); } private Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos) { if ((object)test.Type != typeof(bool)) { throw ParseError(errorPos, "The first expression must be of type 'Boolean'"); } if ((object)expr1.Type != expr2.Type) { Expression expression = ((expr2 != nullLiteral) ? PromoteExpression(expr1, expr2.Type, exact: true) : null); Expression expression2 = ((expr1 != nullLiteral) ? PromoteExpression(expr2, expr1.Type, exact: true) : null); if (expression != null && expression2 == null) { expr1 = expression; } else { if (expression2 == null || expression != null) { string text = ((expr1 != nullLiteral) ? expr1.Type.Name : "null"); string text2 = ((expr2 != nullLiteral) ? expr2.Type.Name : "null"); if (expression != null && expression2 != null) { throw ParseError(errorPos, "Both of the types '{0}' and '{1}' convert to the other", text, text2); } throw ParseError(errorPos, "Neither of the types '{0}' and '{1}' converts to the other", text, text2); } expr2 = expression2; } } return Expression.Condition(test, expr1, expr2); } private Expression ParseNew() { NextToken(); ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); List<DynamicProperty> list = new List<DynamicProperty>(); List<Expression> list2 = new List<Expression>(); while (true) { int pos = token.pos; Expression expression = ParseExpression(); string name; if (TokenIdentifierIs("as")) { NextToken(); name = GetIdentifier(); NextToken(); } else { if (!(expression is MemberExpression memberExpression)) { throw ParseError(pos, "Expression is missing an 'as' clause"); } name = memberExpression.Member.Name; } list2.Add(expression); list.Add(new DynamicProperty(name, expression.Type)); if (token.id != TokenId.Comma) { break; } NextToken(); } ValidateToken(TokenId.CloseParen, "')' or ',' expected"); NextToken(); Type type = DynamicExpression.CreateClass(list); MemberBinding[] array = new MemberBinding[list.Count]; for (int i = 0; i < array.Length; i++) { array[i] = Expression.Bind(type.GetProperty(list[i].Name), list2[i]); } return Expression.MemberInit(Expression.New(type), array); } private Expression ParseLambdaInvocation(LambdaExpression lambda) { int pos = token.pos; NextToken(); Expression[] array = ParseArgumentList(); if (FindMethod(lambda.Type, "Invoke", staticAccess: false, array, out var _) != 1) { throw ParseError(pos, "Argument list incompatible with lambda expression"); } return Expression.Invoke(lambda, array); } private Expression ParseTypeAccess(Type type) { int pos = token.pos; NextToken(); if (token.id == TokenId.Question) { if (!type.IsValueType || IsNullableType(type)) { throw ParseError(pos, "Type '{0}' has no nullable form", GetTypeName(type)); } type = typeof(Nullable<>).MakeGenericType(type); NextToken(); } if (token.id == TokenId.OpenParen) { Expression[] array = ParseArgumentList(); MethodBase method; switch (FindBestMethod(type.GetConstructors(), array, out method)) { case 0: if (array.Length == 1) { return GenerateConversion(array[0], type, pos); } throw ParseError(pos, "No matching constructor in type '{0}'", GetTypeName(type)); case 1: return Expression.New((ConstructorInfo)method, array); default: throw ParseError(pos, "Ambiguous invocation of '{0}' constructor", GetTypeName(type)); } } ValidateToken(TokenId.Dot, "'.' or '(' expected"); NextToken(); return ParseMemberAccess(type, null); } private Expression GenerateConversion(Expression expr, Type type, int errorPos) { Type type2 = expr.Type; if ((object)type2 == type) { return expr; } if (type2.IsValueType && type.IsValueType) { if ((IsNullableType(type2) || IsNullableType(type)) && (object)GetNonNullableType(type2) == GetNonNullableType(type)) { return Expression.Convert(expr, type); } if (((IsNumericType(type2) || IsEnumType(type2)) && IsNumericType(type)) || IsEnumType(type)) { return Expression.ConvertChecked(expr, type); } } if (type2.IsAssignableFrom(type) || type.IsAssignableFrom(type2) || type2.IsInterface || type.IsInterface) { return Expression.Convert(expr, type); } throw ParseError(errorPos, "A value of type '{0}' cannot be converted to type '{1}'", GetTypeName(type2), GetTypeName(type)); } private Expression ParseMemberAccess(Type type, Expression instance) { if (instance != null) { type = instance.Type; } int pos = token.pos; string identifier = GetIdentifier(); NextToken(); if (token.id == TokenId.OpenParen) { if (instance != null && (object)type != typeof(string)) { Type type2 = FindGenericType(typeof(IEnumerable<>), type); if ((object)type2 != null) { Type elementType = type2.GetGenericArguments()[0]; return ParseAggregate(instance, elementType, identifier, pos); } } Expression[] array = ParseArgumentList(); MethodBase method; switch (FindMethod(type, identifier, instance == null, array, out method)) { case 0: throw ParseError(pos, "No applicable method '{0}' exists in type '{1}'", identifier, GetTypeName(type)); case 1: { MethodInfo methodInfo = (MethodInfo)method; if (!IsPredefinedType(methodInfo.DeclaringType)) { throw ParseError(pos, "Methods on type '{0}' are not accessible", GetTypeName(methodInfo.DeclaringType)); } if ((object)methodInfo.ReturnType == typeof(void)) { throw ParseError(pos, "Method '{0}' in type '{1}' does not return a value", identifier, GetTypeName(methodInfo.DeclaringType)); } return Expression.Call(instance, methodInfo, array); } default: throw ParseError(pos, "Ambiguous invocation of method '{0}' in type '{1}'", identifier, GetTypeName(type)); } } MemberInfo memberInfo = FindPropertyOrField(type, identifier, instance == null); if ((object)memberInfo == null) { throw ParseError(pos, "No property or field '{0}' exists in type '{1}'", identifier, GetTypeName(type)); } if (!(memberInfo is PropertyInfo)) { return Expression.Field(instance, (FieldInfo)memberInfo); } return Expression.Property(instance, (PropertyInfo)memberInfo); } private static Type FindGenericType(Type generic, Type type) { while ((object)type != null && (object)type != typeof(object)) { if (type.IsGenericType && (object)type.GetGenericTypeDefinition() == generic) { return type; } if (generic.IsInterface) { Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { Type type3 = FindGenericType(generic, type2); if ((object)type3 != null) { return type3; } } } type = type.BaseType; } return null; } private Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) { ParameterExpression parameterExpression = it; ParameterExpression parameterExpression2 = (it = Expression.Parameter(elementType, "")); Expression[] array = ParseArgumentList(); it = parameterExpression; if (FindMethod(typeof(IEnumerableSignatures), methodName, staticAccess: false, array, out var method) != 1) { throw ParseError(errorPos, "No applicable aggregate method '{0}' exists", methodName); } return Expression.Call(typeArguments: (!(method.Name == "Min") && !(method.Name == "Max")) ? new Type[1] { elementType } : new Type[2] { elementType, array[0].Type }, arguments: (array.Length != 0) ? new Expression[2] { instance, Expression.Lambda(array[0], parameterExpression2) } : new Expression[1] { instance }, type: typeof(Enumerable), methodName: method.Name); } private Expression[] ParseArgumentList() { ValidateToken(TokenId.OpenParen, "'(' expected"); NextToken(); Expression[] result = ((token.id != TokenId.CloseParen) ? ParseArguments() : new Expression[0]); ValidateToken(TokenId.CloseParen, "')' or ',' expected"); NextToken(); return result; } private Expression[] ParseArguments() { List<Expression> list = new List<Expression>(); while (true) { list.Add(ParseExpression()); if (token.id != TokenId.Comma) { break; } NextToken(); } return list.ToArray(); } private Expression ParseElementAccess(Expression expr) { int pos = token.pos; ValidateToken(TokenId.OpenBracket, "'(' expected"); NextToken(); Expression[] array = ParseArguments(); ValidateToken(TokenId.CloseBracket, "']' or ',' expected"); NextToken(); if (expr.Type.IsArray) { if (expr.Type.GetArrayRank() != 1 || array.Length != 1) { throw ParseError(pos, "Indexing of multi-dimensional arrays is not supported"); } Expression expression = PromoteExpression(array[0], typeof(int), exact: true); if (expression == null) { throw ParseError(pos, "Array index must be an integer expression"); } return Expression.ArrayIndex(expr, expression); } MethodBase method; return FindIndexer(expr.Type, array, out method) switch { 0 => throw ParseError(pos, "No applicable indexer exists in type '{0}'", GetTypeName(expr.Type)), 1 => Expression.Call(expr, (MethodInfo)method, array), _ => throw ParseError(pos, "Ambiguous invocation of indexer in type '{0}'", GetTypeName(expr.Type)), }; } private static bool IsPredefinedType(Type type) { Type[] array = predefinedTypes; for (int i = 0; i < array.Length; i++) { if ((object)array[i] == type) { return true; } } return false; } private static bool IsNullableType(Type type) { if (type.IsGenericType) { return (object)type.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } private static Type GetNonNullableType(Type type) { if (!IsNullableType(type)) { return type; } return type.GetGenericArguments()[0]; } private static string GetTypeName(Type type) { Type nonNullableType = GetNonNullableType(type); string text = nonNullableType.Name; if ((object)type != nonNullableType) { text += "?"; } return text; } private static bool IsNumericType(Type type) { return GetNumericTypeKind(type) != 0; } private static bool IsSignedIntegralType(Type type) { return GetNumericTypeKind(type) == 2; } private static bool IsUnsignedIntegralType(Type type) { return GetNumericTypeKind(type) == 3; } private static int GetNumericTypeKind(Type type) { type = GetNonNullableType(type); if (type.IsEnum) { return 0; } switch (Type.GetTypeCode(type)) { case TypeCode.Char: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return 1; case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: return 2; case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return 3; default: return 0; } } private static bool IsEnumType(Type type) { return GetNonNullableType(type).IsEnum; } private void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos) { Expression[] array = new Expression[1] { expr }; if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1) { throw ParseError(errorPos, "Operator '{0}' incompatible with operand type '{1}'", opName, GetTypeName(array[0].Type)); } expr = array[0]; } private void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos) { Expression[] array = new Expression[2] { left, right }; if (FindMethod(signatures, "F", staticAccess: false, array, out var _) != 1) { throw IncompatibleOperandsError(opName, left, right, errorPos); } left = array[0]; right = array[1]; } private Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos) { return ParseError(pos, "Operator '{0}' incompatible with operand types '{1}' and '{2}'", opName, GetTypeName(left.Type), GetTypeName(right.Type)); } private MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance); foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] array = item.FindMembers(MemberTypes.Field | MemberTypes.Property, bindingAttr, Type.FilterNameIgnoreCase, memberName); if (array.Length != 0) { return array[0]; } } return null; } private int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | (staticAccess ? BindingFlags.Static : BindingFlags.Instance); foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] source = item.FindMembers(MemberTypes.Method, bindingAttr, Type.FilterNameIgnoreCase, methodName); int num = FindBestMethod(source.Cast<MethodBase>(), args, out method); if (num != 0) { return num; } } method = null; return 0; } private int FindIndexer(Type type, Expression[] args, out MethodBase method) { foreach (Type item in SelfAndBaseTypes(type)) { MemberInfo[] defaultMembers = item.GetDefaultMembers(); if (defaultMembers.Length != 0) { IEnumerable<MethodBase> methods = from m in defaultMembers.OfType<PropertyInfo>().Select((Func<PropertyInfo, MethodBase>)((PropertyInfo p) => p.GetGetMethod())) where (object)m != null select m; int num = FindBestMethod(methods, args, out method); if (num != 0) { return num; } } } method = null; return 0; } private static IEnumerable<Type> SelfAndBaseTypes(Type type) { if (type.IsInterface) { List<Type> list = new List<Type>(); AddInterface(list, type); return list; } return SelfAndBaseClasses(type); } private static IEnumerable<Type> SelfAndBaseClasses(Type type) { while ((object)type != null) { yield return type; type = type.BaseType; } } private static void AddInterface(List<Type> types, Type type) { if (!types.Contains(type)) { types.Add(type); Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { AddInterface(types, type2); } } } private int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method) { MethodData[] applicable = (from m in methods select new MethodData { MethodBase = m, Parameters = m.GetParameters() } into m where IsApplicable(m, args) select m).ToArray(); if (applicable.Length > 1) { applicable = applicable.Where((MethodData m) => applicable.All((MethodData n) => m == n || IsBetterThan(args, m, n))).ToArray(); } if (applicable.Length == 1) { MethodData methodData = applicable[0]; for (int i = 0; i < args.Length; i++) { args[i] = methodData.Args[i]; } method = methodData.MethodBase; } else { method = null; } return applicable.Length; } private bool IsApplicable(MethodData method, Expression[] args) { if (method.Parameters.Length != args.Length) { return false; } Expression[] array = new Expression[args.Length]; for (int i = 0; i < args.Length; i++) { ParameterInfo parameterInfo = method.Parameters[i]; if (parameterInfo.IsOut) { return false; } Expression expression = PromoteExpression(args[i], parameterInfo.ParameterType, exact: false); if (expression == null) { return false; } array[i] = expression; } method.Args = array; return true; } private Expression PromoteExpression(Expression expr, Type type, bool exact) { if ((object)expr.Type == type) { return expr; } if (expr is ConstantExpression) { ConstantExpression constantExpression = (ConstantExpression)expr; string value; if (constantExpression == nullLiteral) { if (!type.IsValueType || IsNullableType(type)) { return Expression.Constant(null, type); } } else if (literals.TryGetValue(constantExpression, out value)) { Type nonNullableType = GetNonNullableType(type); object obj = null; switch (Type.GetTypeCode(constantExpression.Type)) { case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: obj = ParseNumber(value, nonNullableType); break; case TypeCode.Double: if ((object)nonNullableType == typeof(decimal)) { obj = ParseNumber(value, nonNullableType); } break; case TypeCode.String: obj = ParseEnum(value, nonNullableType); break; } if (obj != null) { return Expression.Constant(obj, type); } } } if (IsCompatibleWith(expr.Type, type)) { if (type.IsValueType || exact) { return Expression.Convert(expr, type); } return expr; } return null; } private static object ParseNumber(string text, Type type) { switch (Type.GetTypeCode(GetNonNullableType(type))) { case TypeCode.SByte: { if (sbyte.TryParse(text, out var result6)) { return result6; } break; } case TypeCode.Byte: { if (byte.TryParse(text, out var result10)) { return result10; } break; } case TypeCode.Int16: { if (short.TryParse(text, out var result2)) { return result2; } break; } case TypeCode.UInt16: { if (ushort.TryParse(text, out var result8)) { return result8; } break; } case TypeCode.Int32: { if (int.TryParse(text, out var result4)) { return result4; } break; } case TypeCode.UInt32: { if (uint.TryParse(text, out var result11)) { return result11; } break; } case TypeCode.Int64: { if (long.TryParse(text, out var result9)) { return result9; } break; } case TypeCode.UInt64: { if (ulong.TryParse(text, out var result7)) { return result7; } break; } case TypeCode.Single: { if (float.TryParse(text, out var result5)) { return result5; } break; } case TypeCode.Double: { if (double.TryParse(text, out var result3)) { return result3; } break; } case TypeCode.Decimal: { if (decimal.TryParse(text, out var result)) { return result; } break; } } return null; } private static object ParseEnum(string name, Type type) { if (type.IsEnum) { MemberInfo[] array = type.FindMembers(MemberTypes.Field, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public, Type.FilterNameIgnoreCase, name); if (array.Length != 0) { return ((FieldInfo)array[0]).GetValue(null); } } return null; } private static bool IsCompatibleWith(Type source, Type target) { if ((object)source == target) { return true; } if (!target.IsValueType) { return target.IsAssignableFrom(source); } Type nonNullableType = GetNonNullableType(source); Type nonNullableType2 = GetNonNullableType(target); if ((object)nonNullableType != source && (object)nonNullableType2 == target) { return false; } TypeCode typeCode = (nonNullableType.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType)); TypeCode typeCode2 = (nonNullableType2.IsEnum ? TypeCode.Object : Type.GetTypeCode(nonNullableType2)); switch (typeCode) { case TypeCode.SByte: switch (typeCode2) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Byte: if ((uint)(typeCode2 - 6) <= 9u) { return true; } break; case TypeCode.Int16: switch (typeCode2) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt16: if ((uint)(typeCode2 - 8) <= 7u) { return true; } break; case TypeCode.Int32: switch (typeCode2) { case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt32: if ((uint)(typeCode2 - 10) <= 5u) { return true; } break; case TypeCode.Int64: if (typeCode2 == TypeCode.Int64 || (uint)(typeCode2 - 13) <= 2u) { return true; } break; case TypeCode.UInt64: if ((uint)(typeCode2 - 12) <= 3u) { return true; } break; case TypeCode.Single: if ((uint)(typeCode2 - 13) <= 1u) { return true; } break; default: if ((object)nonNullableType == nonNullableType2) { return true; } break; } return false; } private static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2) { bool result = false; for (int i = 0; i < args.Length; i++) { int num = CompareConversions(args[i].Type, m1.Parameters[i].ParameterType, m2.Parameters[i].ParameterType); if (num < 0) { return false; } if (num > 0) { result = true; } } return result; } private static int CompareConversions(Type s, Type t1, Type t2) { if ((object)t1 == t2) { return 0; } if ((object)s == t1) { return 1; } if ((object)s == t2) { return -1; } bool flag = IsCompatibleWith(t1, t2); bool flag2 = IsCompatibleWith(t2, t1); if (flag && !flag2) { return 1; } if (flag2 && !flag) { return -1; } if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) { return 1; } if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) { return -1; } return 0; } private Expression GenerateEqual(Expression left, Expression right) { return Expression.Equal(left, right); } private Expression GenerateNotEqual(Expression left, Expression right) { return Expression.NotEqual(left, right); } private Expression GenerateGreaterThan(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.GreaterThan(left, right); } private Expression GenerateGreaterThanEqual(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.GreaterThanOrEqual(left, right); } private Expression GenerateLessThan(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.LessThan(left, right); } private Expression GenerateLessThanEqual(Expression left, Expression right) { if ((object)left.Type == typeof(string)) { return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0)); } return Expression.LessThanOrEqual(left, right); } private Expression GenerateAdd(Expression left, Expression right) { if ((object)left.Type == typeof(string) && (object)right.Type == typeof(string)) { return GenerateStaticMethodCall("Concat", left, right); } return Expression.Add(left, right); } private Expression GenerateSubtract(Expression left, Expression right) { return Expression.Subtract(left, right); } private Expression GenerateStringConcat(Expression left, Expression right) { return Expression.Call(null, typeof(string).GetMethod("Concat", new Type[2] { typeof(object), typeof(object) }), new Expression[2] { left, right }); } private MethodInfo GetStaticMethod(string methodName, Expression left, Expression right) { return left.Type.GetMethod(methodName, new Type[2] { left.Type, right.Type }); } private Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right) { return Expression.Call(null, GetStaticMethod(methodName, left, right), new Expression[2] { left, right }); } private void SetTextPos(int pos) { textPos = pos; ch = ((textPos < textLen) ? text[textPos] : '\0'); } private void NextChar() { if (textPos < textLen) { textPos++; } ch = ((textPos < textLen) ? text[textPos] : '\0'); } private void NextToken() { while (char.IsWhiteSpace(ch)) { NextChar(); } int num = textPos; TokenId id; switch (ch) { case '!': NextChar(); if (ch == '=') { NextChar(); id = TokenId.ExclamationEqual; } else { id = TokenId.Exclamation; } break; case '%': NextChar(); id = TokenId.Percent; break; case '&': NextChar(); if (ch == '&') { NextChar(); id = TokenId.DoubleAmphersand; } else { id = TokenId.Amphersand; } break; case '(': NextChar(); id = TokenId.OpenParen; break; case ')': NextChar(); id = TokenId.CloseParen; break; case '*': NextChar(); id = TokenId.Asterisk; break; case '+': NextChar(); id = TokenId.Plus; break; case ',': NextChar(); id = TokenId.Comma; break; case '-': NextChar(); id = TokenId.Minus; break; case '.': NextChar(); id = TokenId.Dot; break; case '/': NextChar(); id = TokenId.Slash; break; case ':': NextChar(); id = TokenId.Colon; break; case '<': NextChar(); if (ch == '=') { NextChar(); id = TokenId.LessThanEqual; } else if (ch == '>') { NextChar(); id = TokenId.LessGreater; } else { id = TokenId.LessThan; } break; case '=': NextChar(); if (ch == '=') { NextChar(); id = TokenId.DoubleEqual; } else { id = TokenId.Equal; } break; case '>': NextChar(); if (ch == '=') { NextChar(); id = TokenId.GreaterThanEqual; } else { id = TokenId.GreaterThan; } break; case '?': NextChar(); id = TokenId.Question; break; case '[': NextChar(); id = TokenId.OpenBracket; break; case ']': NextChar(); id = TokenId.CloseBracket; break; case '|': NextChar(); if (ch == '|') { NextChar(); id = TokenId.DoubleBar; } else { id = TokenId.Bar; } break; case '"': case '\'': { char c = ch; do { NextChar(); while (textPos < textLen && ch != c) { NextChar(); } if (textPos == textLen) { throw ParseError(textPos, "Unterminated string literal"); } NextChar(); } while (ch == c); id = TokenId.StringLiteral; break; } default: if (char.IsLetter(ch) || ch == '@' || ch == '_') { do { NextChar(); } while (char.IsLetterOrDigit(ch) || ch == '_'); id = TokenId.Identifier; } else if (char.IsDigit(ch)) { id = TokenId.IntegerLiteral; do { NextChar(); } while (char.IsDigit(ch)); if (ch == '.') { id = TokenId.RealLiteral; NextChar(); ValidateDigit(); do { NextChar(); } while (char.IsDigit(ch)); } if (ch == 'E' || ch == 'e') { id = TokenId.RealLiteral; NextChar(); if (ch == '+' || ch == '-') { NextChar(); } ValidateDigit(); do { NextChar(); } while (char.IsDigit(ch)); } if (ch == 'F' || ch == 'f') { NextChar(); } } else { if (textPos != textLen) { throw ParseError(textPos, "Syntax error '{0}'", ch); } id = TokenId.End; } break; } token.id = id; token.text = text.Substring(num, textPos - num); token.pos = num; } private bool TokenIdentifierIs(string id) { if (token.id == TokenId.Identifier) { return string.Equals(id, token.text, StringComparison.OrdinalIgnoreCase); } return false; } private string GetIdentifier() { ValidateToken(TokenId.Identifier, "Identifier expected"); string text = token.text; if (text.Length > 1 && text[0] == '@') { text = text.Substring(1); } return text; } private void ValidateDigit() { if (!char.IsDigit(ch)) { throw ParseError(textPos, "Digit expected"); } } private void ValidateToken(TokenId t, string errorMessage) { if (token.id != t) { throw ParseError(errorMessage); } } private void ValidateToken(TokenId t) { if (token.id != t) { throw ParseError("Syntax error"); } } private Exception ParseError(string format, params object[] args) { return ParseError(token.pos, format, args); } private Exception ParseError(int pos, string format, params object[] args) { return new ParseException(string.Format(CultureInfo.CurrentCulture, format, args), pos); } private static Dictionary<string, object> CreateKeywords() { Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); dictionary.Add("true", trueLiteral); dictionary.Add("false", falseLiteral); dictionary.Add("null", nullLiteral); dictionary.Add(keywordIt, keywordIt); dictionary.Add(keywordIif, keywordIif); dictionary.Add(keywordNew, keywordNew); Type[] array = predefinedTypes; foreach (Type type in array) { dictionary.Add(type.Name, type); } return dictionary; } } internal static class Res { public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once"; public const string ExpressionTypeMismatch = "Expression of type '{0}' expected"; public const string ExpressionExpected = "Expression expected"; public const string InvalidCharacterLiteral = "Character literal must contain exactly one character"; public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'"; public const string InvalidRealLiteral = "Invalid real literal '{0}'"; public const string UnknownIdentifier = "Unknown identifier '{0}'"; public const string NoItInScope = "No 'it' is in scope"; public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments"; public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'"; public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other"; public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other"; public const string MissingAsClause = "Expression is missing an 'as' clause"; public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression"; public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form"; public const string NoMatchingConstructor = "No matching constructor in type '{0}'"; public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor"; public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'"; public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'"; public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible"; public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value"; public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'"; public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'"; public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists"; public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported"; public const string InvalidIndex = "Array index must be an integer expression"; public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'"; public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'"; public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'"; public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'"; public const string UnterminatedStringLiteral = "Unterminated string literal"; public const string InvalidCharacter = "Syntax error '{0}'"; public const string DigitExpected = "Digit expected"; public const string SyntaxError = "Syntax error"; public const string TokenExpected = "{0} expected"; public const string ParseExceptionFormat = "{0} (at index {1})"; public const string ColonExpected = "':' expected"; public const string OpenParenExpected = "'(' expected"; public const string CloseParenOrOperatorExpected = "')' or operator expected"; public const string CloseParenOrCommaExpected = "')' or ',' expected"; public const string DotOrOpenParenExpected = "'.' or '(' expected"; public const string OpenBracketExpected = "'[' expected"; public const string CloseBracketOrCommaExpected = "']' or ',' expected"; public const string IdentifierExpected = "Identifier expected"; } } namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } public static bool forceASCII; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { get { yield break; } } public IEnumerable<JSONNode> DeepChildren { get { foreach (JSONNode child in Children) { foreach (JSONNode deepChild in child.DeepChildren) { yield return deepChild; } } } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, out result)) { return result; } return 0.0; } set { Value = value.ToString(); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { return new JSONString(s); } public static implicit operator string(JSONNode d) { if (!(d == null)) { return d.Value; } return null; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { if (!(d == null)) { return d.AsDouble; } return 0.0; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { if (!(d == null)) { return d.AsFloat; } return 0f; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { if (!(d == null)) { return d.AsInt; } return 0; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { if (!(d == null)) { return d.AsBool; } return false; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } if (!flag) { return a.Equals(b); } return false; } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) { if (quoted) { ctx.Add(tokenName, token); return; } string text = token.ToLower(); switch (text) { case "false": case "true": ctx.Add(tokenName, text == "true"); return; case "null": ctx.Add(tokenName, null); return; } if (double.TryParse(token, out var result)) { ctx.Add(tokenName, result); } else { ctx.Add(tokenName, token); } } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string text = ""; bool flag = false; bool flag2 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(text, stack.Peek()); } text = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } text = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { ParseElement(jSONNode, stringBuilder.ToString(), text, flag2); flag2 = false; } text = ""; stringBuilder.Length = 0; flag2 = false; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; default: stringBuilder.Append(aJSON[i]); break; case '\n': case '\r': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } return jSONNode; } } public class JSONArray : JSONNode { private List<JSONNode> m_List = new List<JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { get { foreach (JSONNode item in m_List) { yield return item; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } } public class JSONObject : JSONNode { private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.ContainsKey(aKey)) { return m_Dict[aKey]; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { get { foreach (KeyValuePair<string, JSONNode> item in m_Dict) { yield return item.Value; } } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (!string.IsNullOrEmpty(aKey)) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(); } set { if (double.TryParse(value, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data); } private static bool IsNumeric(object value) { if (!(value is int) && !(value is uint) && !(value is float) && !(value is double) && !(value is decimal) && !(value is long) && !(value is ulong) && !(value is short) && !(value is ushort) && !(value is sbyte)) { return value is byte; } return true; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node; private string m_Key; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { JSONArray jSONArray = new JSONArray(); jSONArray.Add(value); Set(jSONArray); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, value); Set(jSONObject); } } public override int AsInt { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override float AsFloat { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0f; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override double AsDouble { get { JSONNumber aVal = new JSONNumber(0.0); Set(aVal); return 0.0; } set { JSONNumber aVal = new JSONNumber(value); Set(aVal); } } public override bool AsBool { get { JSONBool aVal = new JSONBool(aData: false); Set(aVal); return false; } set { JSONBool aVal = new JSONBool(value); Set(aVal); } } public override JSONArray AsArray { get { JSONArray jSONArray = new JSONArray(); Set(jSONArray); return jSONArray; } } public override JSONObject AsObject { get { JSONObject jSONObject = new JSONObject(); Set(jSONObject); return jSONObject; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private void Set(JSONNode aVal) { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; } public override void Add(JSONNode aItem) { JSONArray jSONArray = new JSONArray(); jSONArray.Add(aItem); Set(jSONArray); } public override void Add(string aKey, JSONNode aItem) { JSONObject jSONObject = new JSONObject(); jSONObject.Add(aKey, aItem); Set(jSONObject); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } } namespace XUnity.AutoTranslator.Plugin { internal class SceneLoadInformation { public SceneInformation ActiveScene { get; set; } public List<SceneInformation> LoadedScenes { get; set; } public SceneLoadInformation() { LoadedScenes = new List<SceneInformation>(); if (UnityFeatures.SupportsSceneManager) { LoadBySceneManager(); } else { LoadByApplication(); } } public void LoadBySceneManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); ActiveScene = new SceneInformation(((Scene)(ref activeScene)).buildIndex, ((Scene)(ref activeScene)).name); for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); LoadedScenes.Add(new SceneInformation(((Scene)(ref sceneAt)).buildIndex, ((Scene)(ref sceneAt)).name)); } } public void LoadByApplication() { ActiveScene = new SceneInformation(Application.loadedLevel, Application.loadedLevelName); LoadedScenes.Add(new SceneInformation(Application.loadedLevel, Application.loadedLevelName)); } } internal class SceneInformation { public int Id { get; set; } public string Name { get; set; } public SceneInformation(int id, string name) { Id = id; Name = name; } } } namespace XUnity.AutoTranslator.Plugin.Utilities { internal static class TranslationScopeHelper { public static int GetScope(object ui) { if (Settings.EnableTranslationScoping) { try { Component val = (Component)((ui is Component) ? ui : null); if (val != null && Object.op_Implicit((Object)(object)val)) { return GetScopeFromComponent(val); } if (ui is GUIContent) { return -1; } return GetActiveSceneId(); } catch (MissingMemberException ex) { XuaLogger.AutoTranslator.Error((Exception)ex, "A 'missing member' error occurred while retriving translation scope. Disabling translation scopes."); Settings.EnableTranslationScoping = false; } } return -1; } private static int GetScopeFromComponent(Component component) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Scene scene = component.gameObject.scene; return ((Scene)(ref scene)).buildIndex; } public static int GetActiveSceneId() { if (UnityFeatures.SupportsSceneManager) { return GetActiveSceneIdBySceneManager(); } return GetActiveSceneIdByApplication(); } private static int GetActiveSceneIdBySceneManager() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).buildIndex; } public static void RegisterSceneLoadCallback(Action<int> sceneLoaded) { SceneManagerLoader.EnableSceneLoadScanInternal(sceneLoaded); } private static int GetActiveSceneIdByApplication() { return Application.loadedLevel; } } internal static class SceneManagerLoader { public static void EnableSceneLoadScanInternal(Action<int> sceneLoaded) { SceneManager.sceneLoaded += delegate(Scene arg1, LoadSceneMode arg2) { sceneLoaded(((Scene)(ref arg1)).buildIndex); }; } } internal static class TranslationScopes { public const int None = -1; } } namespace XUnity.AutoTranslator.Plugin.Core { public class AutoTranslationPlugin : MonoBehaviour, IMonoBehaviour, IMonoBehaviour_Update, IInternalTranslator, ITranslator, ITranslationRegistry { internal static AutoTranslationPlugin Current; private bool _hasResizedCurrentComponentDuringDiscovery; internal XuaWindow MainWindow; internal TranslationAggregatorWindow TranslationAggregatorWindow; internal TranslationAggregatorOptionsWindow TranslationAggregatorOptionsWindow; internal TranslationManager TranslationManager; internal TextTranslationCache TextCache; internal Dictionary<string, TextTranslationCache> PluginTextCaches = new Dictionary<string, TextTranslationCache>(StringComparer.OrdinalIgnoreCase); internal TextureTranslationCache TextureCache; internal UIResizeCache ResizeCache; internal SpamChecker SpamChecker; private Dictionary<string, UntranslatedText> CachedKeys = new Dictionary<string, UntranslatedText>(StringComparer.Ordinal); private List<Action<ComponentTranslationContext>> _shouldIgnore = new List<Action<ComponentTranslationContext>>(); private List<string> _textsToCopyToClipboardOrdered = new List<string>(); private HashSet<string> _textsToCopyToClipboard = new HashSet<string>(); private float _clipboardUpdated; private HashSet<string> _immediatelyTranslating = new HashSet<string>(); private bool _isInTranslatedMode = true; private bool _textHooksEnabled = true; private float _batchOperationSecondCounter; private bool _hasValidOverrideFont; private bool _hasOverridenFont; private bool _initialized; private bool _started; private bool _temporarilyDisabled; private string _requireSpriteRendererCheckCausedBy; private int _lastSpriteUpdateFrame = -1; private bool _isCalledFromSceneManager; private bool _translationReloadRequest; private bool _hasUiBeenSetup; private static bool _inputSupported; public void Initialize() { Current = this; Paths.Initialize(); HarmonyLoader.Load(); Settings.Configure(); DebugConsole.Enable(); InitializeHarmonyDetourBridge(); InitializeTextTranslationCaches(); HooksSetup.InstallTextHooks(); HooksSetup.InstallImageHooks(); HooksSetup.InstallSpriteRendererHooks(); HooksSetup.InstallTextGetterCompatHooks(); HooksSetup.InstallComponentBasedPluginTranslationHooks(); TextureCache = new TextureTranslationCache(); TextureCache.TextureTranslationFileChanged += TextureCache_TextureTranslationFileChanged; ResizeCache = new UIResizeCache(); TranslationManager = new TranslationManager(); TranslationManager.JobCompleted += OnJobCompleted; TranslationManager.JobFailed += OnJobFailed; TranslationManager.InitializeEndpoints(); SpamChecker = new SpamChecker(TranslationManager); UnityTextParsers.Initialize(); InitializeResourceRedirector(); ValidateConfiguration(); EnableSceneLoadScan(); LoadFallbackFont(); LoadTranslations(reload: false); XuaLogger.AutoTranslator.Info("Loaded XUnity.AutoTranslator into Unity [" + Application.unityVersion + "] game."); } private static void LoadFallbackFont() { try { if (!string.IsNullOrEmpty(Settings.FallbackFontTextMeshPro)) { Object orCreateFallbackFontTextMeshPro = FontCache.GetOrCreateFallbackFontTextMeshPro(); if (TMP_Settings_Properties.FallbackFontAssets == null) { XuaLogger.AutoTranslator.Info("Cannot use fallback font because it is not supported in this version."); return; } if (orCreateFallbackFontTextMeshPro == (Object)null) { XuaLogger.AutoTranslator.Warn("Could not load fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro); return; } ((IList)TMP_Settings_Properties.FallbackFontAssets.Get((object)null)).Add(orCreateFallbackFontTextMeshPro); XuaLogger.AutoTranslator.Info("Loaded fallback font for TextMesh Pro: " + Settings.FallbackFontTextMeshPro); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while trying to load fallback font for TextMesh Pro."); } } private static void InitializeHarmonyDetourBridge() { try { if (Settings.InitializeHarmonyDetourBridge) { InitializeHarmonyDetourBridgeSafe(); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing harmony detour bridge."); } } private static void InitializeHarmonyDetourBridgeSafe() { HarmonyDetourBridge.Init(true, (Type)0); } private void InitializeTextTranslationCaches() { try { TextCache = new TextTranslationCache(); TextCache.TextTranslationFileChanged += TextCache_TextTranslationFileChanged; DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Settings.TranslationsPath, "plugins")); if (directoryInfo.Exists) { DirectoryInfo[] directories = directoryInfo.GetDirectories(); foreach (DirectoryInfo directoryInfo2 in directories) { TextTranslationCache value = new TextTranslationCache(directoryInfo2); PluginTextCaches.Add(directoryInfo2.Name, value); } } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing text translation caches."); } } private void TextCache_TextTranslationFileChanged() { _translationReloadRequest = true; } private void TextureCache_TextureTranslationFileChanged() { _translationReloadRequest = true; } private static void EnableLogAllLoadedResources() { ResourceRedirection.LogAllLoadedResources = true; } private void EnableTextAssetLoadedHandler() { new TextAssetLoadedHandler(); } private void InitializeResourceRedirector() { try { if (Settings.LogAllLoadedResources) { EnableLogAllLoadedResources(); } if (Settings.EnableTextAssetRedirector) { EnableTextAssetLoadedHandler(); } } catch (Exception ex) { XuaLogger.AutoTranslator.Error(ex, "An error occurred while initializing resource redirectors."); } } private void InitializeGUI() { Dis
BepInEx/plugins/XUnity.AutoTranslator/XUnity.AutoTranslator.Plugin.ExtProtocol.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Package that contains a simple inter-process protocol format used in XUnity.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyTitle("XUnity.AutoTranslator.Plugin.ExtProtocol")] [assembly: AssemblyVersion("1.0.1.0")] namespace XUnity.AutoTranslator.Plugin.ExtProtocol; public class ConfigurationMessage : ProtocolMessage { public static readonly string Type = "4"; public string Config { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); Config = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.Write(Config); } } public static class ExtProtocolConvert { private static readonly Dictionary<string, Type> IdToType; private static readonly Dictionary<Type, string> TypeToId; static ExtProtocolConvert() { IdToType = new Dictionary<string, Type>(); TypeToId = new Dictionary<Type, string>(); Register(TranslationRequest.Type, typeof(TranslationRequest)); Register(TranslationResponse.Type, typeof(TranslationResponse)); Register(TranslationError.Type, typeof(TranslationError)); Register(ConfigurationMessage.Type, typeof(ConfigurationMessage)); } public static void Register(string id, Type type) { IdToType[id] = type; TypeToId[type] = id; } public static string Encode(ProtocolMessage message) { StringWriter stringWriter = new StringWriter(); string value = TypeToId[message.GetType()]; stringWriter.WriteLine(value); message.Encode(stringWriter); return Convert.ToBase64String(Encoding.UTF8.GetBytes(stringWriter.ToString()), Base64FormattingOptions.None); } public static ProtocolMessage Decode(string message) { StringReader stringReader = new StringReader(Encoding.UTF8.GetString(Convert.FromBase64String(message))); string key = stringReader.ReadLine(); ProtocolMessage obj = (ProtocolMessage)Activator.CreateInstance(IdToType[key]); obj.Decode(stringReader); return obj; } } public abstract class ProtocolMessage { public Guid Id { get; set; } internal abstract void Decode(TextReader reader); internal abstract void Encode(TextWriter writer); } public enum StatusCode { OK = 0, Blocked = 1, Unknown = 1000 } public class TranslationError : ProtocolMessage { public static readonly string Type = "3"; public string Reason { get; set; } public StatusCode FailureCode { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); FailureCode = (StatusCode)int.Parse(reader.ReadLine()); Reason = reader.ReadToEnd(); } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine((int)FailureCode); writer.Write(Reason); } } public class TranslationRequest : ProtocolMessage { public static readonly string Type = "1"; private string[] _untranslatedTexts; public string SourceLanguage { get; set; } public string DestinationLanguage { get; set; } public string[] UntranslatedTexts => _untranslatedTexts ?? (_untranslatedTexts = UntranslatedTextInfos.Select((TransmittableUntranslatedTextInfo x) => x.UntranslatedText).ToArray()); public TransmittableUntranslatedTextInfo[] UntranslatedTextInfos { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); SourceLanguage = reader.ReadLine(); DestinationLanguage = reader.ReadLine(); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); TransmittableUntranslatedTextInfo[] array = new TransmittableUntranslatedTextInfo[num]; for (int i = 0; i < num; i++) { TransmittableUntranslatedTextInfo transmittableUntranslatedTextInfo = new TransmittableUntranslatedTextInfo(); transmittableUntranslatedTextInfo.Decode(reader); array[i] = transmittableUntranslatedTextInfo; } UntranslatedTextInfos = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(SourceLanguage); writer.WriteLine(DestinationLanguage); writer.WriteLine(UntranslatedTextInfos.Length.ToString(CultureInfo.InvariantCulture)); TransmittableUntranslatedTextInfo[] untranslatedTextInfos = UntranslatedTextInfos; for (int i = 0; i < untranslatedTextInfos.Length; i++) { untranslatedTextInfos[i].Encode(writer); } } } public class TranslationResponse : ProtocolMessage { public static readonly string Type = "2"; public string[] TranslatedTexts { get; set; } internal override void Decode(TextReader reader) { base.Id = new Guid(reader.ReadLine()); int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } TranslatedTexts = array; } internal override void Encode(TextWriter writer) { writer.WriteLine(base.Id.ToString()); writer.WriteLine(TranslatedTexts.Length.ToString(CultureInfo.InvariantCulture)); string[] translatedTexts = TranslatedTexts; foreach (string s in translatedTexts) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } } public class TransmittableUntranslatedTextInfo { public string[] ContextBefore { get; set; } public string UntranslatedText { get; set; } public string[] ContextAfter { get; set; } public TransmittableUntranslatedTextInfo(string[] contextBefore, string untranslatedText, string[] contextAfter) { ContextBefore = contextBefore; UntranslatedText = untranslatedText; ContextAfter = contextAfter; } public TransmittableUntranslatedTextInfo() { } internal void Encode(TextWriter writer) { string[] contextBefore = ContextBefore; writer.WriteLine(((contextBefore != null) ? contextBefore.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextBefore != null) { string[] contextBefore2 = ContextBefore; foreach (string s in contextBefore2) { string value = Convert.ToBase64String(Encoding.UTF8.GetBytes(s), Base64FormattingOptions.None); writer.WriteLine(value); } } string[] contextAfter = ContextAfter; writer.WriteLine(((contextAfter != null) ? contextAfter.Length : 0).ToString(CultureInfo.InvariantCulture)); if (ContextAfter != null) { string[] contextBefore2 = ContextAfter; foreach (string s2 in contextBefore2) { string value2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s2), Base64FormattingOptions.None); writer.WriteLine(value2); } } string value3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(UntranslatedText), Base64FormattingOptions.None); writer.WriteLine(value3); } internal void Decode(TextReader reader) { int num = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array = new string[num]; for (int i = 0; i < num; i++) { string s = reader.ReadLine(); string @string = Encoding.UTF8.GetString(Convert.FromBase64String(s)); array[i] = @string; } ContextBefore = array; int num2 = int.Parse(reader.ReadLine(), CultureInfo.InvariantCulture); string[] array2 = new string[num2]; for (int j = 0; j < num2; j++) { string s2 = reader.ReadLine(); string string2 = Encoding.UTF8.GetString(Convert.FromBase64String(s2)); array2[j] = string2; } ContextAfter = array2; string s3 = reader.ReadLine(); string string3 = Encoding.UTF8.GetString(Convert.FromBase64String(s3)); UntranslatedText = string3; } }
BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.BepInEx.dll
Decompiled a year agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("2.1.0")] [assembly: AssemblyProduct("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyTitle("XUnity.ResourceRedirector.BepInEx")] [assembly: AssemblyVersion("2.1.0.0")] namespace XUnity.ResourceRedirector.BepInEx; [BepInPlugin("gravydevsupreme.xunity.resourceredirector", "XUnity Resource Redirector", "2.1.0")] public class ResourceRedirectorPlugin : BaseUnityPlugin { public static ConfigEntry<bool> LogAllLoadedResources { get; set; } public static ConfigEntry<bool> LogCallbackOrder { get; set; } private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown LogAllLoadedResources = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log all loaded resources"), false, (ConfigDescription)null); ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; LogAllLoadedResources.SettingChanged += delegate { ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; }; LogCallbackOrder = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Diagnostics", "Log callback order"), false, (ConfigDescription)null); ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; LogCallbackOrder.SettingChanged += delegate { ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; }; ((BaseUnityPlugin)this).Config.ConfigReloaded += Config_ConfigReloaded; } private static void Config_ConfigReloaded(object sender, EventArgs e) { ResourceRedirection.LogAllLoadedResources = LogAllLoadedResources.Value; ResourceRedirection.LogCallbackOrder = LogCallbackOrder.Value; } }
BepInEx/plugins/XUnity.ResourceRedirector/XUnity.ResourceRedirector.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using UnityEngine; using XUnity.Common.Constants; using XUnity.Common.Extensions; using XUnity.Common.Harmony; using XUnity.Common.Logging; using XUnity.Common.MonoMod; using XUnity.Common.Utilities; using XUnity.ResourceRedirector.Constants; using XUnity.ResourceRedirector.Hooks; using XUnity.ResourceRedirector.Properties; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("gravydevsupreme")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Main development dependency for XUnity Resource Redirector.")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("2.1.0")] [assembly: AssemblyProduct("XUnity.ResourceRedirector")] [assembly: AssemblyTitle("XUnity.ResourceRedirector")] [assembly: AssemblyVersion("2.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace XUnity.ResourceRedirector { internal class AssetBundleExtensionData { private string _normalizedPath; private string _path; public string NormalizedPath { get { if (Path != null && _normalizedPath == null) { _normalizedPath = StringExtensions.MakeRelativePath(Path.ToLowerInvariant(), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } } public string Path { get { return _path; } set { if (_path != value) { _path = value; _normalizedPath = null; } } } } public static class AssetBundleHelper { internal static string PathForLoadedInMemoryBundle; public static AssetBundle CreateEmptyAssetBundle() { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); return AssetBundle.LoadFromMemory(empty); } public static AssetBundleCreateRequest CreateEmptyAssetBundleRequest() { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); return AssetBundle.LoadFromMemoryAsync(empty); } public static AssetBundle LoadFromMemory(string path, byte[] binary, uint crc) { try { PathForLoadedInMemoryBundle = path; return AssetBundle.LoadFromMemory(binary, crc); } finally { PathForLoadedInMemoryBundle = null; } } public static AssetBundleCreateRequest LoadFromMemoryAsync(string path, byte[] binary, uint crc) { try { PathForLoadedInMemoryBundle = path; return AssetBundle.LoadFromMemoryAsync(binary, crc); } finally { PathForLoadedInMemoryBundle = null; } } public static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset) { return LoadFromFileWithRandomizedCabIfRequired(path, crc, offset, confirmFileExists: true); } internal static AssetBundle LoadFromFileWithRandomizedCabIfRequired(string path, uint crc, ulong offset, bool confirmFileExists) { AssetBundle val = AssetBundle.LoadFromFile(path, crc, offset); if ((Object)(object)val == (Object)null && (!confirmFileExists || File.Exists(path))) { byte[] array; using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)) { long num = fileStream.Length - (long)offset; fileStream.Seek((long)offset, SeekOrigin.Begin); array = StreamExtensions.ReadFully((Stream)fileStream, (int)num); } CabHelper.RandomizeCabWithAnyLength(array); XuaLogger.ResourceRedirector.Warn("Randomized CAB for '" + path + "' in order to load it because another asset bundle already uses its CAB-string. You can ignore the previous error message, but this is likely caused by two mods incorrectly using the same CAB-string."); return AssetBundle.LoadFromMemory(array); } return val; } } public class AssetBundleLoadedContext { private string _normalizedPath; public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; set; } internal bool SkipRemainingPostfixes { get; private set; } internal AssetBundleLoadedContext(AssetBundleLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetBundleLoadingContext : IAssetBundleLoadingContext { private string _normalizedPath; public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; private set; } internal bool SkipAllPostfixes { get; private set; } internal AssetBundleLoadingContext(AssetBundleLoadingParameters parameters) { Parameters = parameters; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete() { Complete(skipRemainingPrefixes: true, true, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true) { Complete(skipRemainingPrefixes, skipOriginalCall, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetBundleLoadingParameters { public string Path { get; set; } public uint Crc { get; set; } public ulong Offset { get; set; } public Stream Stream { get; set; } public uint ManagedReadBufferSize { get; } public byte[] Binary { get; set; } public AssetBundleLoadType LoadType { get; } internal AssetBundleLoadingParameters(byte[] data, string path, uint crc, ulong offset, Stream stream, uint managedReadBufferSize, AssetBundleLoadType loadType) { Binary = data; Path = path; Crc = crc; Offset = offset; Stream = stream; ManagedReadBufferSize = managedReadBufferSize; LoadType = loadType; } } public enum AssetBundleLoadType { LoadFromFile = 1, LoadFromMemory, LoadFromStream } public class AssetLoadedContext : IAssetOrResourceLoadedContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private BackingFieldOrArray _backingField; public AssetLoadedParameters Parameters { get; } public AssetBundle Bundle { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPostfixes { get; private set; } internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object[] assets) { Parameters = parameters; Bundle = bundle; _backingField = new BackingFieldOrArray(assets); } internal AssetLoadedContext(AssetLoadedParameters parameters, AssetBundle bundle, Object asset) { Parameters = parameters; Bundle = bundle; _backingField = new BackingFieldOrArray(asset); } public bool HasReferenceBeenRedirectedBefore(Object asset) { return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false; } public string GetUniqueFileSystemAssetPath(Object asset) { ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset); if (orCreateExtensionData.FullFileSystemAssetPath == null) { string text = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle)?.NormalizedPath; string path = (string.IsNullOrEmpty(text) ? "unnamed_assetbundle" : text.ToLowerInvariant()); string name = asset.name; if (!string.IsNullOrEmpty(name)) { path = Path.Combine(path, name.ToLowerInvariant()); } else { string text2 = null; if (Assets.Length > 1) { int num = Array.IndexOf(Assets, asset); text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index"); } path = Path.Combine(path, (Parameters.LoadType == AssetLoadType.LoadMainAsset) ? "main_asset" : ("unnamed_asset" + text2)); } path = StringExtensions.UseCorrectDirectorySeparators(path); orCreateExtensionData.FullFileSystemAssetPath = path; } return orCreateExtensionData.FullFileSystemAssetPath; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetLoadedParameters { public string Name { get; } public Type Type { get; } public AssetLoadType LoadType { get; } internal AssetLoadedParameters(string name, Type type, AssetLoadType loadType) { Name = name; Type = type; LoadType = loadType; } } public class AssetLoadingContext : IAssetLoadingContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private BackingFieldOrArray _backingField; public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; private set; } internal bool SkipAllPostfixes { get; private set; } internal AssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class AssetLoadingParameters { public string Name { get; set; } public Type Type { get; set; } public AssetLoadType LoadType { get; } internal AssetLoadingParameters(string name, Type type, AssetLoadType loadType) { Name = name; Type = type; LoadType = loadType; } internal AssetLoadedParameters ToAssetLoadedParameters() { return new AssetLoadedParameters(Name, Type, LoadType); } } public enum AssetLoadType { LoadMainAsset = 1, LoadByType, LoadNamed, LoadNamedWithSubAssets } internal class AsyncAssetBundleLoadInfo { public AssetBundleLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public bool SkipAllPostfixes { get; } public AsyncAssetBundleLoadingResolve ResolveType { get; } public AsyncAssetBundleLoadInfo(AssetBundleLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetBundleLoadingResolve resolveType) { Parameters = parameters; Bundle = bundle; SkipAllPostfixes = skipAllPostfixes; ResolveType = resolveType; } } public class AsyncAssetBundleLoadingContext : IAssetBundleLoadingContext { private string _normalizedPath; private AssetBundle _bundle; private AssetBundleCreateRequest _request; public AssetBundleLoadingParameters Parameters { get; } public AssetBundleCreateRequest Request { get { return _request; } set { _request = value; ResolveType = AsyncAssetBundleLoadingResolve.ThroughRequest; } } public AssetBundle Bundle { get { return _bundle; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Bundle property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _bundle = value; ResolveType = AsyncAssetBundleLoadingResolve.ThroughBundle; } } public AsyncAssetBundleLoadingResolve ResolveType { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; set; } internal bool SkipAllPostfixes { get; private set; } internal AsyncAssetBundleLoadingContext(AssetBundleLoadingParameters parameters) { Parameters = parameters; } public string GetNormalizedPath() { if (_normalizedPath == null && Parameters.Path != null) { _normalizedPath = StringExtensions.MakeRelativePath(StringExtensions.UseCorrectDirectorySeparators(Parameters.Path.ToLowerInvariant()), EnvironmentEx.LoweredCurrentDirectory); } return _normalizedPath; } public void Complete() { Complete(skipRemainingPrefixes: true, true, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true) { Complete(skipRemainingPrefixes, skipOriginalCall, true); } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public enum AsyncAssetBundleLoadingResolve { ThroughRequest, ThroughBundle } internal class AsyncAssetLoadInfo { public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public bool SkipAllPostfixes { get; } public AsyncAssetLoadingResolve ResolveType { get; } public Object[] Assets { get; } public AsyncAssetLoadInfo(AssetLoadingParameters parameters, AssetBundle bundle, bool skipAllPostfixes, AsyncAssetLoadingResolve resolveType, Object[] assets) { Parameters = parameters; Bundle = bundle; SkipAllPostfixes = skipAllPostfixes; ResolveType = resolveType; Assets = assets; } } public class AsyncAssetLoadingContext : IAssetLoadingContext { private AssetBundleExtensionData _ext; private bool _lookedForExt; private Object[] _assets; private AssetBundleRequest _request; private BackingFieldOrArray _backingField; public AssetLoadingParameters Parameters { get; } public AssetBundle Bundle { get; } public AssetBundleRequest Request { get { return _request; } set { _request = value; ResolveType = AsyncAssetLoadingResolve.ThroughRequest; } } public Object[] Assets { get { return _backingField.Array; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _backingField.Array = value; ResolveType = AsyncAssetLoadingResolve.ThroughAssets; } } public Object Asset { get { return _backingField.Field; } set { if (!ResourceRedirection.SyncOverAsyncEnabled) { throw new InvalidOperationException("Trying to set the Assets/Asset property in async load operation while 'SyncOverAsyncAssetLoads' is disabled is not allowed. Consider settting the Request property instead if possible or enabling 'SyncOverAsyncAssetLoads' through the method 'ResourceRedirection.EnableSyncOverAsyncAssetLoads()'."); } _backingField.Field = value; ResolveType = AsyncAssetLoadingResolve.ThroughAssets; } } public AsyncAssetLoadingResolve ResolveType { get; set; } internal bool SkipRemainingPrefixes { get; private set; } internal bool SkipOriginalCall { get; set; } internal bool SkipAllPostfixes { get; private set; } internal AsyncAssetLoadingContext(AssetLoadingParameters parameters, AssetBundle bundle) { Parameters = parameters; Bundle = bundle; } public string GetAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.Path; } public string GetNormalizedAssetBundlePath() { if (!_lookedForExt) { _lookedForExt = true; _ext = ExtensionDataHelper.GetExtensionData<AssetBundleExtensionData>((object)Bundle); } return _ext?.NormalizedPath; } public void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true) { SkipRemainingPrefixes = skipRemainingPrefixes; if (skipOriginalCall.HasValue) { SkipOriginalCall = skipOriginalCall.Value; } if (skipAllPostfixes.HasValue) { SkipAllPostfixes = skipAllPostfixes.Value; } } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public enum AsyncAssetLoadingResolve { ThroughRequest, ThroughAssets } internal struct BackingFieldOrArray { private Object _field; private Object[] _array; private BackingSource _source; public Object Field { get { if (_source == BackingSource.None) { return null; } if (_source == BackingSource.SingleField) { return _field; } if (_array == null || _array.Length == 0) { return null; } return _array[0]; } set { _field = value; _array = null; _source = BackingSource.SingleField; } } public Object[] Array { get { if (_source == BackingSource.Array) { return _array; } if (_field == (Object)null) { Array = (Object[])(object)new Object[0]; } else { Array = (Object[])(object)new Object[1] { _field }; } return _array; } set { _field = null; _array = value; _source = BackingSource.Array; } } public BackingFieldOrArray(Object field) { _field = field; _array = null; _source = BackingSource.SingleField; } public BackingFieldOrArray(Object[] array) { _field = null; _array = array; _source = BackingSource.Array; } public IEnumerable<Object> IterateObjects() { if (_array != null) { Object[] array = _array; for (int i = 0; i < array.Length; i++) { yield return array[i]; } } else if (_field != (Object)null) { yield return _field; } } } internal enum BackingSource : byte { None, SingleField, Array } public static class CallbackPriority { public const int Default = 0; } public enum HookBehaviour { OneCallbackPerLoadCall = 1, OneCallbackPerResourceLoaded } public interface IAssetBundleLoadingContext { AssetBundleLoadingParameters Parameters { get; } AssetBundle Bundle { get; set; } string GetNormalizedPath(); void Complete(); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true); void DisableRecursion(); } public interface IAssetLoadingContext { AssetLoadingParameters Parameters { get; } AssetBundle Bundle { get; } Object[] Assets { get; set; } Object Asset { get; set; } string GetAssetBundlePath(); string GetNormalizedAssetBundlePath(); void Complete(bool skipRemainingPrefixes = true, bool? skipOriginalCall = true, bool? skipAllPostfixes = true); void DisableRecursion(); } public interface IAssetOrResourceLoadedContext { Object[] Assets { get; set; } Object Asset { get; set; } bool HasReferenceBeenRedirectedBefore(Object asset); string GetUniqueFileSystemAssetPath(Object asset); void Complete(bool skipRemainingPostfixes = true); void DisableRecursion(); } internal class PrioritizedCallback { public static PrioritizedCallback<TCallback> Create<TCallback>(TCallback item, int priority) where TCallback : Delegate { return new PrioritizedCallback<TCallback>(item, priority); } } internal class PrioritizedCallback<TCallback> : PrioritizedCallback, IComparable<PrioritizedCallback<TCallback>>, IEquatable<PrioritizedCallback<TCallback>> where TCallback : Delegate { public TCallback Callback { get; } public int Priority { get; } public Type TargetType { get; set; } public bool IsBeingCalled { get; set; } public PrioritizedCallback(TCallback callback, int priority) { Callback = callback; Priority = priority; TargetType = callback.Target?.GetType(); } public int CompareTo(PrioritizedCallback<TCallback> other) { return other.Priority.CompareTo(Priority); } public override bool Equals(object obj) { return Equals(obj as PrioritizedCallback<TCallback>); } public bool Equals(PrioritizedCallback<TCallback> other) { return EqualityComparer<TCallback>.Default.Equals(Callback, other.Callback); } public override int GetHashCode() { return -1406788065 * -1521134295 + EqualityComparer<TCallback>.Default.GetHashCode(Callback); } public override string ToString() { return "[" + Priority + "] " + (TargetType?.Name ?? Callback.Method.DeclaringType?.Name) + "." + Callback.Method?.Name; } } internal class ResourceExtensionData { public bool HasBeenRedirected { get; set; } public string FullFileSystemAssetPath { get; set; } } public class ResourceLoadedContext : IAssetOrResourceLoadedContext { private BackingFieldOrArray _backingField; public ResourceLoadedParameters Parameters { get; } public Object[] Assets { get { return _backingField.Array; } set { _backingField.Array = value; } } public Object Asset { get { return _backingField.Field; } set { _backingField.Field = value; } } internal bool SkipRemainingPostfixes { get; set; } internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object[] assets) { Parameters = parameters; _backingField = new BackingFieldOrArray(assets); } internal ResourceLoadedContext(ResourceLoadedParameters parameters, Object asset) { Parameters = parameters; _backingField = new BackingFieldOrArray(asset); } public bool HasReferenceBeenRedirectedBefore(Object asset) { return ExtensionDataHelper.GetExtensionData<ResourceExtensionData>((object)asset)?.HasBeenRedirected ?? false; } public string GetUniqueFileSystemAssetPath(Object asset) { ResourceExtensionData orCreateExtensionData = ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)asset); if (orCreateExtensionData.FullFileSystemAssetPath == null) { string text = string.Empty; if (!string.IsNullOrEmpty(Parameters.Path)) { text = Parameters.Path.ToLowerInvariant(); } if (Parameters.LoadType == ResourceLoadType.LoadByType) { string name = asset.name; if (!string.IsNullOrEmpty(name)) { text = Path.Combine(text, name.ToLowerInvariant()); } else { string text2 = null; if (Assets.Length > 1) { int num = Array.IndexOf(Assets, asset); text2 = ((num != -1) ? ("_" + num.ToString(CultureInfo.InvariantCulture)) : "_with_unknown_index"); } text = Path.Combine(text, "unnamed_asset" + text2); } } text = StringExtensions.UseCorrectDirectorySeparators(text); orCreateExtensionData.FullFileSystemAssetPath = text; } return orCreateExtensionData.FullFileSystemAssetPath; } public void Complete(bool skipRemainingPostfixes = true) { SkipRemainingPostfixes = skipRemainingPostfixes; } public void DisableRecursion() { ResourceRedirection.RecursionEnabled = false; } } public class ResourceLoadedParameters { public string Path { get; set; } public Type Type { get; set; } public ResourceLoadType LoadType { get; } internal ResourceLoadedParameters(string path, Type type, ResourceLoadType loadType) { Path = path; Type = type; LoadType = loadType; } } public enum ResourceLoadType { LoadByType = 1, LoadNamed, LoadNamedBuiltIn } public static class ResourceRedirection { private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Action<AssetLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<AssetLoadedContext>>> PostfixRedirectionsForAssetsPerResource = new List<PrioritizedCallback<Action<AssetLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerCall = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>(); private static readonly List<PrioritizedCallback<Action<ResourceLoadedContext>>> PostfixRedirectionsForResourcesPerResource = new List<PrioritizedCallback<Action<ResourceLoadedContext>>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetsPerCall = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetsPerCall = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAssetBundles = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Delegate>> PrefixRedirectionsForAsyncAssetBundles = new List<PrioritizedCallback<Delegate>>(); private static readonly List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> PostfixRedirectionsForAssetBundles = new List<PrioritizedCallback<Action<AssetBundleLoadedContext>>>(); private static Action<AssetBundleLoadingContext> _emulateAssetBundles; private static Action<AsyncAssetBundleLoadingContext> _emulateAssetBundlesAsync; private static Action<AssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmpty; private static Action<AsyncAssetBundleLoadingContext> _redirectionMissingAssetBundlesToEmptyAsync; private static bool _enabledRandomizeCabIfConflict = false; private static Action<AssetBundleLoadingContext> _enableCabRandomizationPrefix; private static Action<AsyncAssetBundleLoadingContext> _enableCabRandomizationPrefixAsync; private static Action<AssetBundleLoadedContext> _enableCabRandomizationPostfix; private static bool _initialized = false; private static bool _initializedSyncOverAsyncEnabled = false; private static bool _logAllLoadedResources = false; private static bool _isFiringAssetBundle; private static bool _isFiringResource; private static bool _isFiringAsset; private static bool _isRecursionDisabledPermanently; internal static bool RecursionEnabled = true; internal static bool SyncOverAsyncEnabled = false; public static bool LogAllLoadedResources { get { return _logAllLoadedResources; } set { if (value) { Initialize(); } _logAllLoadedResources = value; } } public static bool LogCallbackOrder { get; set; } public static void Initialize() { if (!_initialized) { _initialized = true; HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.GeneralHooks, false); } } public static void EnableSyncOverAsyncAssetLoads() { Initialize(); if (!_initializedSyncOverAsyncEnabled) { _initializedSyncOverAsyncEnabled = true; SyncOverAsyncEnabled = true; HookingHelper.PatchAll((IEnumerable<Type>)ResourceAndAssetHooks.SyncOverAsyncHooks, false); } } public static void DisableRecursionPermanently() { _isRecursionDisabledPermanently = true; } public static void EnableEmulateAssetBundles(int priority, string emulationDirectory) { if (_emulateAssetBundles == null && _emulateAssetBundlesAsync == null) { _emulateAssetBundles = delegate(AssetBundleLoadingContext ctx) { HandleAssetBundleEmulation<AssetBundleLoadingContext>(ctx, SetBundle); }; _emulateAssetBundlesAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleAssetBundleEmulation<AsyncAssetBundleLoadingContext>(ctx, SetRequest); }; RegisterAssetBundleLoadingHook(priority, _emulateAssetBundles); RegisterAsyncAssetBundleLoadingHook(priority, _emulateAssetBundlesAsync); } void HandleAssetBundleEmulation<T>(T context, Action<T, string> changeBundle) where T : IAssetBundleLoadingContext { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile) { string normalizedPath = context.GetNormalizedPath(); string text = Path.Combine(emulationDirectory, normalizedPath); if (File.Exists(text)) { changeBundle(context, text); ref T reference = ref context; T val = default(T); if (val == null) { val = reference; reference = ref val; } reference.Complete(skipRemainingPrefixes: true, true); XuaLogger.ResourceRedirector.Debug("Redirected asset bundle: '" + context.Parameters.Path + "' => '" + text + "'"); } } } static void SetBundle(AssetBundleLoadingContext context, string path) { context.Bundle = AssetBundle.LoadFromFile(path, context.Parameters.Crc, context.Parameters.Offset); } static void SetRequest(AsyncAssetBundleLoadingContext context, string path) { context.Request = AssetBundle.LoadFromFileAsync(path, context.Parameters.Crc, context.Parameters.Offset); } } public static void DisableEmulateAssetBundles() { if (_emulateAssetBundles != null && _emulateAssetBundlesAsync != null) { UnregisterAssetBundleLoadingHook(_emulateAssetBundles); UnregisterAsyncAssetBundleLoadingHook(_emulateAssetBundlesAsync); _emulateAssetBundles = null; _emulateAssetBundlesAsync = null; } } public static void EnableRedirectMissingAssetBundlesToEmptyAssetBundle(int priority) { if (_redirectionMissingAssetBundlesToEmpty == null && _redirectionMissingAssetBundlesToEmptyAsync == null) { _redirectionMissingAssetBundlesToEmpty = delegate(AssetBundleLoadingContext ctx) { HandleMissingBundle<AssetBundleLoadingContext>(ctx, SetBundle); }; _redirectionMissingAssetBundlesToEmptyAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleMissingBundle<AsyncAssetBundleLoadingContext>(ctx, SetRequest); }; RegisterAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmpty); RegisterAsyncAssetBundleLoadingHook(priority, _redirectionMissingAssetBundlesToEmptyAsync); } static void HandleMissingBundle<TContext>(TContext context, Action<TContext, byte[]> changeBundle) where TContext : IAssetBundleLoadingContext { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile && !File.Exists(context.Parameters.Path)) { byte[] empty = Resources.empty; CabHelper.RandomizeCab(empty); changeBundle(context, empty); ref TContext reference = ref context; TContext val = default(TContext); if (val == null) { val = reference; reference = ref val; } reference.Complete(skipRemainingPrefixes: true, true); XuaLogger.ResourceRedirector.Warn("Tried to load non-existing asset bundle: " + context.Parameters.Path); } } static void SetBundle(AssetBundleLoadingContext context, byte[] assetBundleData) { AssetBundle bundle = AssetBundle.LoadFromMemory(assetBundleData); context.Bundle = bundle; } static void SetRequest(AsyncAssetBundleLoadingContext context, byte[] assetBundleData) { AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(assetBundleData); context.Request = request; } } public static void EnableRandomizeCabIfConflict(int priority, bool forceRandomizeWhenInMemory) { if (_enabledRandomizeCabIfConflict) { return; } _enabledRandomizeCabIfConflict = true; if (forceRandomizeWhenInMemory) { _enableCabRandomizationPrefix = delegate(AssetBundleLoadingContext ctx) { HandleCabRandomizePrefix(ctx); }; _enableCabRandomizationPrefixAsync = delegate(AsyncAssetBundleLoadingContext ctx) { HandleCabRandomizePrefix(ctx); }; RegisterAssetBundleLoadingHook(priority, _enableCabRandomizationPrefix); RegisterAsyncAssetBundleLoadingHook(priority, _enableCabRandomizationPrefixAsync); } _enableCabRandomizationPostfix = delegate(AssetBundleLoadedContext ctx) { HandleCabRandomizePostfix(ctx); }; RegisterAssetBundleLoadedHook(priority, _enableCabRandomizationPostfix); void HandleCabRandomizePostfix(AssetBundleLoadedContext context) { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromFile) { if ((Object)(object)context.Bundle == (Object)null && File.Exists(context.Parameters.Path)) { XuaLogger.ResourceRedirector.Warn("The asset bundle '" + context.Parameters.Path + "' could not be loaded likely due to conflicting CAB-string. Retrying in-memory with randomized CAB-string."); byte[] array; using (FileStream fileStream = new FileStream(context.Parameters.Path, FileMode.Open, FileAccess.Read)) { long length = fileStream.Length; long offset = (long)context.Parameters.Offset; long num = length - offset; fileStream.Seek(offset, SeekOrigin.Begin); array = StreamExtensions.ReadFully((Stream)fileStream, (int)num); } if (!forceRandomizeWhenInMemory) { CabHelper.RandomizeCabWithAnyLength(array); } AssetBundle val = AssetBundle.LoadFromMemory(array, 0u); if ((Object)(object)val != (Object)null) { context.Bundle = val; context.Complete(); } } } else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory) { if ((Object)(object)context.Bundle == (Object)null && !forceRandomizeWhenInMemory) { string text = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed"; XuaLogger.ResourceRedirector.Warn("Could not load an in-memory asset bundle (" + text + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string."); CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary); AssetBundle val2 = AssetBundle.LoadFromMemory(context.Parameters.Binary, 0u); if ((Object)(object)val2 != (Object)null) { context.Bundle = val2; context.Complete(); } } } else if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromStream && (Object)(object)context.Bundle == (Object)null) { string text2 = AssetBundleHelper.PathForLoadedInMemoryBundle ?? "Unnamed"; XuaLogger.ResourceRedirector.Warn("Could not load a stream asset bundle (" + text2 + ") likely due to conflicting CAB-string. Retrying with randomized CAB-string."); byte[] array2 = StreamExtensions.ReadFully(context.Parameters.Stream, 0); if (!forceRandomizeWhenInMemory) { CabHelper.RandomizeCabWithAnyLength(array2); } AssetBundle val3 = AssetBundle.LoadFromMemory(array2, 0u); if ((Object)(object)val3 != (Object)null) { context.Bundle = val3; context.Complete(); } } } static void HandleCabRandomizePrefix(IAssetBundleLoadingContext context) { if (context.Parameters.LoadType == AssetBundleLoadType.LoadFromMemory) { CabHelper.RandomizeCabWithAnyLength(context.Parameters.Binary); } } } public static void DisableRandomizeCabIfConflict() { if (_enabledRandomizeCabIfConflict) { _enabledRandomizeCabIfConflict = false; if (_enableCabRandomizationPrefix != null) { UnregisterAssetBundleLoadingHook(_enableCabRandomizationPrefix); _enableCabRandomizationPrefix = null; } if (_enableCabRandomizationPrefixAsync != null) { UnregisterAsyncAssetBundleLoadingHook(_enableCabRandomizationPrefixAsync); _enableCabRandomizationPrefixAsync = null; } if (_enableCabRandomizationPostfix != null) { UnregisterAssetBundleLoadedHook(_enableCabRandomizationPostfix); _enableCabRandomizationPostfix = null; } } } public static void DisableRedirectMissingAssetBundlesToEmptyAssetBundle() { if (_redirectionMissingAssetBundlesToEmpty != null && _redirectionMissingAssetBundlesToEmptyAsync != null) { UnregisterAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmpty); UnregisterAsyncAssetBundleLoadingHook(_redirectionMissingAssetBundlesToEmptyAsync); _redirectionMissingAssetBundlesToEmpty = null; _redirectionMissingAssetBundlesToEmptyAsync = null; } } internal static bool TryGetAssetBundleLoadInfo(AssetBundleRequest request, out AsyncAssetLoadInfo result) { result = ExtensionDataHelper.GetExtensionData<AsyncAssetLoadInfo>((object)request); return result != null; } internal static bool TryGetAssetBundle(AssetBundleCreateRequest request, out AsyncAssetBundleLoadInfo result) { result = ExtensionDataHelper.GetExtensionData<AsyncAssetBundleLoadInfo>((object)request); return result != null; } internal static bool ShouldBlockAsyncOperationMethods(AssetBundleRequest operation) { if (TryGetAssetBundleLoadInfo(operation, out var result)) { return result.ResolveType == AsyncAssetLoadingResolve.ThroughAssets; } return false; } internal static bool ShouldBlockAsyncOperationMethods(AssetBundleCreateRequest operation) { if (TryGetAssetBundle(operation, out var result)) { return result.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle; } return false; } internal static bool ShouldBlockAsyncOperationMethods(AsyncOperation operation) { if (SyncOverAsyncEnabled) { AssetBundleRequest operation2 = default(AssetBundleRequest); if (!ObjectExtensions.TryCastTo<AssetBundleRequest>((object)operation, ref operation2) || !ShouldBlockAsyncOperationMethods(operation2)) { AssetBundleCreateRequest operation3 = default(AssetBundleCreateRequest); if (ObjectExtensions.TryCastTo<AssetBundleCreateRequest>((object)operation, ref operation3)) { return ShouldBlockAsyncOperationMethods(operation3); } return false; } return true; } return false; } internal static AssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundle bundle) { AssetBundleLoadingContext assetBundleLoadingContext = new AssetBundleLoadingContext(parameters); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { bundle = null; return assetBundleLoadingContext; } try { _isFiringAssetBundle = true; if (_logAllLoadedResources) { XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle: (" + assetBundleLoadingContext.GetNormalizedPath() + ")."); } List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetBundles = PrefixRedirectionsForAssetBundles; int count = prefixRedirectionsForAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AssetBundleLoadingContext> action) { action(assetBundleLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2) { action2(assetBundleLoadingContext); } if (assetBundleLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoading event."); } finally { _isFiringAssetBundle = false; } bundle = assetBundleLoadingContext.Bundle; return assetBundleLoadingContext; } internal static AssetBundleLoadedContext Hook_AssetBundleLoaded_Postfix(AssetBundleLoadingParameters parameters, ref AssetBundle bundle) { AssetBundleLoadedContext assetBundleLoadedContext = new AssetBundleLoadedContext(parameters, bundle); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { bundle = null; return assetBundleLoadedContext; } try { _isFiringAssetBundle = true; List<PrioritizedCallback<Action<AssetBundleLoadedContext>>> postfixRedirectionsForAssetBundles = PostfixRedirectionsForAssetBundles; int count = postfixRedirectionsForAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(assetBundleLoadedContext); if (assetBundleLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetBundleLoaded event."); } finally { _isFiringAssetBundle = false; } bundle = assetBundleLoadedContext.Bundle; return assetBundleLoadedContext; } internal static AsyncAssetBundleLoadingContext Hook_AssetBundleLoading_Prefix(AssetBundleLoadingParameters parameters, out AssetBundleCreateRequest request) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown AsyncAssetBundleLoadingContext asyncAssetBundleLoadingContext = new AsyncAssetBundleLoadingContext(parameters); if (_isFiringAssetBundle && (_isRecursionDisabledPermanently || !RecursionEnabled)) { request = null; return asyncAssetBundleLoadingContext; } try { _isFiringAssetBundle = true; if (_logAllLoadedResources) { XuaLogger.ResourceRedirector.Debug("Loading Asset Bundle (async): (" + asyncAssetBundleLoadingContext.GetNormalizedPath() + ")."); } List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetBundles = PrefixRedirectionsForAsyncAssetBundles; int count = prefixRedirectionsForAsyncAssetBundles.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetBundles[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AsyncAssetBundleLoadingContext> action) { action(asyncAssetBundleLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetBundleLoadingContext> action2) { action2(asyncAssetBundleLoadingContext); } if (asyncAssetBundleLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetBundleLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetBundleLoading event."); } finally { _isFiringAssetBundle = false; } if (asyncAssetBundleLoadingContext.ResolveType == AsyncAssetBundleLoadingResolve.ThroughRequest) { request = asyncAssetBundleLoadingContext.Request; } else { if (asyncAssetBundleLoadingContext.ResolveType != AsyncAssetBundleLoadingResolve.ThroughBundle) { throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetBundleLoadingContext.ResolveType); } request = new AssetBundleCreateRequest(); if (!asyncAssetBundleLoadingContext.SkipOriginalCall) { XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true."); asyncAssetBundleLoadingContext.SkipOriginalCall = true; } } return asyncAssetBundleLoadingContext; } internal static void Hook_AssetBundleLoading_Postfix(AsyncAssetBundleLoadingContext context, AssetBundleCreateRequest request) { if (request != null) { ExtensionDataHelper.SetExtensionData<AsyncAssetBundleLoadInfo>((object)request, new AsyncAssetBundleLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType)); } } internal static void Hook_AssetLoading_Postfix(AsyncAssetLoadingContext context, AssetBundleRequest request) { if (request != null) { ExtensionDataHelper.SetExtensionData<AsyncAssetLoadInfo>((object)request, new AsyncAssetLoadInfo(context.Parameters, context.Bundle, context.SkipAllPostfixes, context.ResolveType, context.Assets)); } } internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset) { Object[] assets = null; AssetLoadingContext result = Hook_AssetLoading_Prefix(parameters, parentBundle, ref assets); if (assets == null || assets.Length == 0) { asset = null; return result; } if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoadeding event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; return result; } if (assets.Length == 1) { asset = assets[0]; } return result; } internal static AssetLoadingContext Hook_AssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets) { AssetLoadingContext assetLoadingContext = new AssetLoadingContext(parameters, bundle); try { if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return assetLoadingContext; } _isFiringAsset = true; List<PrioritizedCallback<Delegate>> prefixRedirectionsForAssetsPerCall = PrefixRedirectionsForAssetsPerCall; int count = prefixRedirectionsForAssetsPerCall.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAssetsPerCall[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AssetLoadingContext> action) { action(assetLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2) { action2(assetLoadingContext); } if (assetLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = assetLoadingContext.Assets; } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoading event."); } finally { _isFiringAsset = false; } return assetLoadingContext; } internal static AsyncAssetLoadingContext Hook_AsyncAssetLoading_Prefix(AssetLoadingParameters parameters, AssetBundle bundle, ref AssetBundleRequest request) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown AsyncAssetLoadingContext asyncAssetLoadingContext = new AsyncAssetLoadingContext(parameters, bundle); try { if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return asyncAssetLoadingContext; } _isFiringAsset = true; List<PrioritizedCallback<Delegate>> prefixRedirectionsForAsyncAssetsPerCall = PrefixRedirectionsForAsyncAssetsPerCall; int count = prefixRedirectionsForAsyncAssetsPerCall.Count; for (int i = 0; i < count; i++) { PrioritizedCallback<Delegate> prioritizedCallback = prefixRedirectionsForAsyncAssetsPerCall[i]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; if (prioritizedCallback.Callback is Action<AsyncAssetLoadingContext> action) { action(asyncAssetLoadingContext); } else if (prioritizedCallback.Callback is Action<IAssetLoadingContext> action2) { action2(asyncAssetLoadingContext); } if (asyncAssetLoadingContext.SkipRemainingPrefixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AsyncAssetLoading event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } if (asyncAssetLoadingContext.ResolveType == AsyncAssetLoadingResolve.ThroughRequest) { request = asyncAssetLoadingContext.Request; } else { if (asyncAssetLoadingContext.ResolveType != AsyncAssetLoadingResolve.ThroughAssets) { throw new InvalidOperationException("Found invalid ResolveType on context: " + asyncAssetLoadingContext.ResolveType); } request = new AssetBundleRequest(); if (!asyncAssetLoadingContext.SkipOriginalCall) { XuaLogger.ResourceRedirector.Warn("Resolving sync over async asset load, but 'SkipOriginalCall' was not set to true. Forcing it to true."); asyncAssetLoadingContext.SkipOriginalCall = true; } } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AsyncAssetLoading event."); } finally { _isFiringAsset = false; } return asyncAssetLoadingContext; } internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle parentBundle, ref Object asset) { Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]); Hook_AssetLoaded_Postfix(parameters, parentBundle, ref assets); if (assets == null || assets.Length == 0) { asset = null; } else if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in AssetLoaded event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; } else if (assets.Length == 1) { asset = assets[0]; } } internal static void Hook_AssetLoaded_Postfix(AssetLoadingParameters parameters, AssetBundle bundle, ref Object[] assets) { FireAssetLoadedEvent(parameters.ToAssetLoadedParameters(), bundle, ref assets); } internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object asset) { Object[] assets = (Object[])(object)((!(asset == (Object)null)) ? new Object[1] { asset } : new Object[0]); Hook_ResourceLoaded_Postfix(parameters, ref assets); if (assets == null || assets.Length == 0) { asset = null; } else if (assets.Length > 1) { XuaLogger.ResourceRedirector.Warn("Illegal behaviour by redirection handler in ResourceLoaded event. Returned more than one asset to call requiring only a single asset."); asset = assets[0]; } else if (assets.Length == 1) { asset = assets[0]; } } internal static void Hook_ResourceLoaded_Postfix(ResourceLoadedParameters parameters, ref Object[] assets) { FireResourceLoadedEvent(parameters, ref assets); } internal static void FireAssetLoadedEvent(AssetLoadedParameters parameters, AssetBundle assetBundle, ref Object[] assets) { Object[] array = assets?.ToArray(); try { AssetLoadedContext assetLoadedContext = new AssetLoadedContext(parameters, assetBundle, assets); if (_isFiringAsset && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return; } _isFiringAsset = true; if (_logAllLoadedResources && assets != null) { for (int i = 0; i < assets.Length; i++) { Object val = assets[i]; if (val != (Object)null) { string uniqueFileSystemAssetPath = assetLoadedContext.GetUniqueFileSystemAssetPath(val); XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ")."); } } } List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerCall = PostfixRedirectionsForAssetsPerCall; int count = postfixRedirectionsForAssetsPerCall.Count; for (int j = 0; j < count; j++) { PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = postfixRedirectionsForAssetsPerCall[j]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(assetLoadedContext); if (assetLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking AssetLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = assetLoadedContext.Assets; if (assetLoadedContext.SkipRemainingPostfixes || assets == null) { return; } int num = assets.Length; for (int k = 0; k < num; k++) { Object val2 = assets[k]; if (val2 != (Object)null) { AssetLoadedContext assetLoadedContext2 = new AssetLoadedContext(parameters, assetBundle, val2); List<PrioritizedCallback<Action<AssetLoadedContext>>> postfixRedirectionsForAssetsPerResource = PostfixRedirectionsForAssetsPerResource; int count2 = postfixRedirectionsForAssetsPerResource.Count; for (int l = 0; l < count2; l++) { PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback2 = postfixRedirectionsForAssetsPerResource[l]; if (prioritizedCallback2.IsBeingCalled) { continue; } try { prioritizedCallback2.IsBeingCalled = true; prioritizedCallback2.Callback(assetLoadedContext2); if (assetLoadedContext2.Asset != (Object)null) { assets[k] = assetLoadedContext2.Asset; } else { XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in AssetLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}."); } if (assetLoadedContext2.SkipRemainingPostfixes) { break; } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking AssetLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback2.IsBeingCalled = false; } } } else { XuaLogger.ResourceRedirector.Error("Found unexpected null asset during AssetLoaded event."); } } } catch (Exception ex3) { XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking AssetLoaded event."); } finally { _isFiringAsset = false; if (array != null) { Object[] array2 = array; for (int m = 0; m < array2.Length; m++) { ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true; } } } } internal static void FireResourceLoadedEvent(ResourceLoadedParameters parameters, ref Object[] assets) { Object[] array = assets?.ToArray(); try { ResourceLoadedContext resourceLoadedContext = new ResourceLoadedContext(parameters, assets); if (_isFiringResource && (_isRecursionDisabledPermanently || !RecursionEnabled)) { return; } _isFiringResource = true; if (_logAllLoadedResources && assets != null) { for (int i = 0; i < assets.Length; i++) { Object val = assets[i]; if (val != (Object)null) { string uniqueFileSystemAssetPath = resourceLoadedContext.GetUniqueFileSystemAssetPath(val); XuaLogger.ResourceRedirector.Debug("Loaded Asset: '" + ObjectExtensions.GetUnityType((object)val).FullName + "', Load Type: '" + parameters.LoadType.ToString() + "', Unique Path: (" + uniqueFileSystemAssetPath + ")."); } } } List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerCall = PostfixRedirectionsForResourcesPerCall; int count = postfixRedirectionsForResourcesPerCall.Count; for (int j = 0; j < count; j++) { PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = postfixRedirectionsForResourcesPerCall[j]; if (prioritizedCallback.IsBeingCalled) { continue; } try { prioritizedCallback.IsBeingCalled = true; prioritizedCallback.Callback(resourceLoadedContext); if (resourceLoadedContext.SkipRemainingPostfixes) { break; } } catch (Exception ex) { XuaLogger.ResourceRedirector.Error(ex, "An error occurred while invoking ResourceLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback.IsBeingCalled = false; } } assets = resourceLoadedContext.Assets; if (resourceLoadedContext.SkipRemainingPostfixes || assets == null) { return; } int num = assets.Length; for (int k = 0; k < num; k++) { Object val2 = assets[k]; if (val2 != (Object)null) { ResourceLoadedContext resourceLoadedContext2 = new ResourceLoadedContext(parameters, val2); List<PrioritizedCallback<Action<ResourceLoadedContext>>> postfixRedirectionsForResourcesPerResource = PostfixRedirectionsForResourcesPerResource; int count2 = postfixRedirectionsForResourcesPerResource.Count; for (int l = 0; l < count2; l++) { PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback2 = postfixRedirectionsForResourcesPerResource[l]; if (prioritizedCallback2.IsBeingCalled) { continue; } try { prioritizedCallback2.IsBeingCalled = true; prioritizedCallback2.Callback(resourceLoadedContext2); if (resourceLoadedContext2.Asset != (Object)null) { assets[k] = resourceLoadedContext2.Asset; } else { XuaLogger.ResourceRedirector.Warn($"Illegal behaviour by redirection handler in ResourceLoaded event. You must not remove an asset reference when hooking with behaviour {HookBehaviour.OneCallbackPerResourceLoaded}."); } if (resourceLoadedContext2.SkipRemainingPostfixes) { break; } } catch (Exception ex2) { XuaLogger.ResourceRedirector.Error(ex2, "An error occurred while invoking ResourceLoaded event."); } finally { RecursionEnabled = true; prioritizedCallback2.IsBeingCalled = false; } } } else { XuaLogger.ResourceRedirector.Error("Found unexpected null asset during ResourceLoaded event."); } } } catch (Exception ex3) { XuaLogger.ResourceRedirector.Error(ex3, "An error occurred while invoking ResourceLoaded event."); } finally { _isFiringResource = false; if (array != null) { Object[] array2 = array; for (int m = 0; m < array2.Length; m++) { ExtensionDataHelper.GetOrCreateExtensionData<ResourceExtensionData>((object)array2[m]).HasBeenRedirected = true; } } } } private static void LogEventRegistration(string eventType, IEnumerable callbacks) { XuaLogger.ResourceRedirector.Debug("Registered new callback for " + eventType + "."); LogNewCallbackOrder(eventType, callbacks); } private static void LogEventUnregistration(string eventType, IEnumerable callbacks) { XuaLogger.ResourceRedirector.Debug("Unregistered callback for " + eventType + "."); LogNewCallbackOrder(eventType, callbacks); } private static void LogNewCallbackOrder(string eventType, IEnumerable callbacks) { if (!LogCallbackOrder) { return; } XuaLogger.ResourceRedirector.Debug("New callback order for " + eventType + ":"); foreach (object callback in callbacks) { XuaLogger.ResourceRedirector.Debug(callback.ToString()); } } public static void RegisterAssetBundleLoadedHook(int priority, Action<AssetBundleLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<AssetBundleLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetBundleLoadedContext>>>(PostfixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles); } public static void RegisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action) { RegisterAssetBundleLoadedHook(0, action); } public static void UnregisterAssetBundleLoadedHook(Action<AssetBundleLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PostfixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Action<AssetBundleLoadedContext>> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoaded", PostfixRedirectionsForAssetBundles); } public static void RegisterAssetLoadingHook(int priority, Action<AssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAssetLoadingHook(Action<AssetLoadingContext> action) { RegisterAssetLoadingHook(0, action); } public static void UnregisterAssetLoadingHook(Action<AssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAsyncAssetLoadingHook(int priority, Action<AsyncAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback); LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); } public static void RegisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action) { RegisterAsyncAssetLoadingHook(0, action); } public static void UnregisterAsyncAssetLoadingHook(Action<AsyncAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); } public static void RegisterAsyncAndSyncAssetLoadingHook(int priority, Action<IAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetsPerCall.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetsPerCall, prioritizedCallback); LogEventRegistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action) { RegisterAsyncAndSyncAssetLoadingHook(0, action); } public static void UnregisterAsyncAndSyncAssetLoadingHook(Action<IAssetLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetLoading", PrefixRedirectionsForAsyncAssetsPerCall); PrefixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetLoading", PrefixRedirectionsForAssetsPerCall); } public static void RegisterAssetLoadedHook(HookBehaviour behaviour, int priority, Action<AssetLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<AssetLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForAssetsPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForAssetsPerResource.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); switch (behaviour) { case HookBehaviour.OneCallbackPerLoadCall: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerCall, prioritizedCallback); LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerCall); break; case HookBehaviour.OneCallbackPerResourceLoaded: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<AssetLoadedContext>>>(PostfixRedirectionsForAssetsPerResource, prioritizedCallback); LogEventRegistration("AssetLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForAssetsPerResource); break; } } public static void RegisterAssetLoadedHook(HookBehaviour behaviour, Action<AssetLoadedContext> action) { RegisterAssetLoadedHook(behaviour, 0, action); } public static void UnregisterAssetLoadedHook(Action<AssetLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } if (PostfixRedirectionsForAssetsPerCall.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForAssetsPerCall); } if (PostfixRedirectionsForAssetsPerResource.RemoveAll((PrioritizedCallback<Action<AssetLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("AssetLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForAssetsPerResource); } } public static void RegisterAssetBundleLoadingHook(int priority, Action<AssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); } public static void RegisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action) { RegisterAssetBundleLoadingHook(0, action); } public static void UnregisterAssetBundleLoadingHook(Action<AssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); } public static void RegisterAsyncAssetBundleLoadingHook(int priority, Action<AsyncAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAsyncAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback); LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action) { RegisterAsyncAssetBundleLoadingHook(0, action); } public static void UnregisterAsyncAssetBundleLoadingHook(Action<AsyncAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAndSyncAssetBundleLoadingHook(int priority, Action<IAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Delegate> prioritizedCallback = PrioritizedCallback.Create((Delegate)action, priority); if (PrefixRedirectionsForAssetBundles.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAssetBundles, prioritizedCallback); LogEventRegistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); ListExtensions.BinarySearchInsert<PrioritizedCallback<Delegate>>(PrefixRedirectionsForAsyncAssetBundles, prioritizedCallback); LogEventRegistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action) { RegisterAsyncAndSyncAssetBundleLoadingHook(0, action); } public static void UnregisterAsyncAndSyncAssetBundleLoadingHook(Action<IAssetBundleLoadingContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrefixRedirectionsForAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AssetBundleLoading", PrefixRedirectionsForAssetBundles); PrefixRedirectionsForAsyncAssetBundles.RemoveAll((PrioritizedCallback<Delegate> x) => object.Equals(x.Callback, action)); LogEventUnregistration("AsyncAssetBundleLoading", PrefixRedirectionsForAsyncAssetBundles); } public static void RegisterResourceLoadedHook(HookBehaviour behaviour, int priority, Action<ResourceLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } PrioritizedCallback<Action<ResourceLoadedContext>> prioritizedCallback = PrioritizedCallback.Create(action, priority); if (PostfixRedirectionsForResourcesPerCall.Contains(prioritizedCallback) || PostfixRedirectionsForResourcesPerResource.Contains(prioritizedCallback)) { throw new ArgumentException("This callback has already been registered.", "action"); } Initialize(); switch (behaviour) { case HookBehaviour.OneCallbackPerLoadCall: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerCall, prioritizedCallback); LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerCall); break; case HookBehaviour.OneCallbackPerResourceLoaded: ListExtensions.BinarySearchInsert<PrioritizedCallback<Action<ResourceLoadedContext>>>(PostfixRedirectionsForResourcesPerResource, prioritizedCallback); LogEventRegistration("ResourceLoaded (" + behaviour.ToString() + ")", PostfixRedirectionsForResourcesPerResource); break; } } public static void RegisterResourceLoadedHook(HookBehaviour behaviour, Action<ResourceLoadedContext> action) { RegisterResourceLoadedHook(behaviour, 0, action); } public static void UnregisterResourceLoadedHook(Action<ResourceLoadedContext> action) { if (action == null) { throw new ArgumentNullException("action"); } if (PostfixRedirectionsForResourcesPerCall.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerLoadCall.ToString() + ")", PostfixRedirectionsForResourcesPerCall); } if (PostfixRedirectionsForResourcesPerResource.RemoveAll((PrioritizedCallback<Action<ResourceLoadedContext>> x) => x.Callback == action) > 0) { LogEventRegistration("ResourceLoaded (" + HookBehaviour.OneCallbackPerResourceLoaded.ToString() + ")", PostfixRedirectionsForResourcesPerResource); } } } } namespace XUnity.ResourceRedirector.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("XUnity.ResourceRedirector.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] empty => (byte[])ResourceManager.GetObject("empty", resourceCulture); internal Resources() { } } } namespace XUnity.ResourceRedirector.Hooks { internal static class ResourceAndAssetHooks { public static readonly Type[] GeneralHooks = new Type[21] { typeof(AssetBundle_LoadFromFileAsync_Hook), typeof(AssetBundle_LoadFromFile_Hook), typeof(AssetBundle_LoadFromMemoryAsync_Hook), typeof(AssetBundle_LoadFromMemory_Hook), typeof(AssetBundle_LoadFromStreamAsync_Hook), typeof(AssetBundle_LoadFromStream_Hook), typeof(AssetBundle_mainAsset_Hook), typeof(AssetBundle_returnMainAsset_Hook), typeof(AssetBundle_Load_Hook), typeof(AssetBundle_LoadAsync_Hook), typeof(AssetBundle_LoadAll_Hook), typeof(AssetBundle_LoadAsset_Internal_Hook), typeof(AssetBundle_LoadAssetAsync_Internal_Hook), typeof(AssetBundle_LoadAssetWithSubAssets_Internal_Hook), typeof(AssetBundle_LoadAssetWithSubAssetsAsync_Internal_Hook), typeof(AssetBundleRequest_asset_Hook), typeof(AssetBundleRequest_allAssets_Hook), typeof(Resources_Load_Hook), typeof(Resources_LoadAll_Hook), typeof(Resources_GetBuiltinResource_Old_Hook), typeof(Resources_GetBuiltinResource_New_Hook) }; public static readonly Type[] SyncOverAsyncHooks = new Type[10] { typeof(AssetBundleCreateRequest_assetBundle_Hook), typeof(AssetBundleCreateRequest_DisableCompatibilityChecks_Hook), typeof(AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook), typeof(AsyncOperation_isDone_Hook), typeof(AsyncOperation_progress_Hook), typeof(AsyncOperation_priority_Hook), typeof(AsyncOperation_set_priority_Hook), typeof(AsyncOperation_allowSceneActivation_Hook), typeof(AsyncOperation_set_allowSceneActivation_Hook), typeof(AsyncOperation_Finalize_Hook) }; } internal static class AssetBundleCreateRequest_assetBundle_Hook { private delegate AssetBundle OriginalMethod(AssetBundleCreateRequest __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundleCreateRequest != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Property((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "assetBundle")?.GetGetMethod(); } private static bool Prefix(AssetBundleCreateRequest __instance, ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state) { if (ResourceRedirection.TryGetAssetBundle(__instance, out __state)) { if (__state.ResolveType == AsyncAssetBundleLoadingResolve.ThroughBundle) { __result = __state.Bundle; return false; } return true; } return true; } private static void Postfix(ref AssetBundle __result, ref AsyncAssetBundleLoadInfo __state) { if (__state == null) { return; } if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state != null) { string path = __state.Parameters.Path; if (path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = path; } } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(AssetBundleCreateRequest __instance) { AssetBundle __result = null; AsyncAssetBundleLoadInfo __state = null; if (Prefix(__instance, ref __result, ref __state)) { __result = _original(__instance); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundleCreateRequest_DisableCompatibilityChecks_Hook { private delegate void OriginalMethod(AssetBundleCreateRequest __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) == null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "DisableCompatibilityChecks", new Type[0]); } private static bool Prefix(AssetBundleCreateRequest __instance) { return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static void MM_Detour(AssetBundleCreateRequest __instance) { if (Prefix(__instance)) { _original(__instance); } } } internal static class AssetBundleCreateRequest_SetEnableCompatibilityChecks_Hook { private delegate void OriginalMethod(AssetBundleCreateRequest __instance, bool set); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return (object)AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }) != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundleCreateRequest = UnityTypes.AssetBundleCreateRequest; return AccessToolsShim.Method((assetBundleCreateRequest != null) ? assetBundleCreateRequest.ClrType : null, "SetEnableCompatibilityChecks", new Type[1] { typeof(bool) }); } private static bool Prefix(AssetBundleCreateRequest __instance, bool set) { return !ResourceRedirection.ShouldBlockAsyncOperationMethods(__instance); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static void MM_Detour(AssetBundleCreateRequest __instance, bool set) { if (Prefix(__instance, set)) { _original(__instance, set); } } } internal static class AssetBundle_LoadFromFileAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(string path, uint crc, ulong offset); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFileAsync_Internal", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFileAsync", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); } return methodInfo; } private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; path = parameters2.Path; crc = parameters2.Crc; offset = parameters2.Offset; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(string path, uint crc, ulong offset) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state)) { __result = _original(path, crc, offset); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromFile_Hook { private delegate AssetBundle OriginalMethod(string path, uint crc, ulong offset); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromFile_Internal", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromFile", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }); } return methodInfo; } private static bool Prefix(ref string path, ref uint crc, ref ulong offset, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, path, crc, offset, null, 0u, AssetBundleLoadType.LoadFromFile); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; path = parameters2.Path; crc = parameters2.Crc; offset = parameters2.Offset; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(string path, uint crc, ulong offset) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref path, ref crc, ref offset, ref __result, ref __state)) { __result = _original(path, crc, offset); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromMemoryAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(byte[] binary, uint crc); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemoryAsync_Internal", new Type[2] { typeof(byte[]), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemoryAsync", new Type[2] { typeof(byte[]), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; binary = parameters2.Binary; crc = parameters2.Crc; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(byte[] binary, uint crc) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref binary, ref crc, ref __result, ref __state)) { __result = _original(binary, crc); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromMemory_Hook { private delegate AssetBundle OriginalMethod(byte[] binary, uint crc); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromMemory_Internal", new Type[2] { typeof(byte[]), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromMemory", new Type[2] { typeof(byte[]), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref byte[] binary, ref uint crc, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(binary, null, crc, 0uL, null, 0u, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; binary = parameters2.Binary; crc = parameters2.Crc; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(byte[] binary, uint crc) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref binary, ref crc, ref __result, ref __state)) { __result = _original(binary, crc); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromStreamAsync_Hook { private delegate AssetBundleCreateRequest OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamAsyncInternal", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStreamAsync", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; stream = parameters2.Stream; crc = parameters2.Crc; managedReadBufferSize = parameters2.ManagedReadBufferSize; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundleCreateRequest __result, ref AsyncAssetBundleLoadingContext __state) { ResourceRedirection.Hook_AssetBundleLoading_Postfix(__state, __result); } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundleCreateRequest MM_Detour(Stream stream, uint crc, uint managedReadBufferSize) { AssetBundleCreateRequest __result = null; AsyncAssetBundleLoadingContext __state = null; if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state)) { __result = _original(stream, crc, managedReadBufferSize); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_LoadFromStream_Hook { private delegate AssetBundle OriginalMethod(Stream stream, uint crc, uint managedReadBufferSize); private static OriginalMethod _original; private static bool Prepare(object instance) { return UnityTypes.AssetBundle != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; MethodInfo methodInfo = AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "LoadFromStreamInternal", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); if ((object)methodInfo == null) { TypeContainer assetBundle2 = UnityTypes.AssetBundle; methodInfo = AccessToolsShim.Method((assetBundle2 != null) ? assetBundle2.ClrType : null, "LoadFromStream", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }); } return methodInfo; } private static bool Prefix(ref Stream stream, ref uint crc, ref uint managedReadBufferSize, ref AssetBundle __result, ref AssetBundleLoadingContext __state) { AssetBundleLoadingParameters parameters = new AssetBundleLoadingParameters(null, null, crc, 0uL, stream, managedReadBufferSize, AssetBundleLoadType.LoadFromMemory); __state = ResourceRedirection.Hook_AssetBundleLoading_Prefix(parameters, out __result); AssetBundleLoadingParameters parameters2 = __state.Parameters; stream = parameters2.Stream; crc = parameters2.Crc; managedReadBufferSize = parameters2.ManagedReadBufferSize; return !__state.SkipOriginalCall; } private static void Postfix(ref AssetBundle __result, ref AssetBundleLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetBundleLoaded_Postfix(__state.Parameters, ref __result); } if ((Object)(object)__result != (Object)null && __state.Parameters.Path != null) { ExtensionDataHelper.GetOrCreateExtensionData<AssetBundleExtensionData>((object)__result).Path = __state.Parameters.Path; } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static AssetBundle MM_Detour(Stream stream, uint crc, uint managedReadBufferSize) { AssetBundle __result = null; AssetBundleLoadingContext __state = null; if (Prefix(ref stream, ref crc, ref managedReadBufferSize, ref __result, ref __state)) { __result = _original(stream, crc, managedReadBufferSize); } Postfix(ref __result, ref __state); return __result; } } internal static class AssetBundle_mainAsset_Hook { private delegate Object OriginalMethod(AssetBundle __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) == null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return AccessToolsShim.Property((assetBundle != null) ? assetBundle.ClrType : null, "mainAsset")?.GetGetMethod(); } private static bool Prefix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state) { AssetLoadingParameters parameters = new AssetLoadingParameters(null, null, AssetLoadType.LoadMainAsset); __state = ResourceRedirection.Hook_AssetLoading_Prefix(parameters, __instance, ref __result); return !__state.SkipOriginalCall; } private static void Postfix(AssetBundle __instance, ref Object __result, ref AssetLoadingContext __state) { if (!__state.SkipAllPostfixes) { ResourceRedirection.Hook_AssetLoaded_Postfix(__state.Parameters, __instance, ref __result); } } private static void MM_Init(object detour) { _original = DetourExtensions.GenerateTrampolineEx<OriginalMethod>(detour); } private static Object MM_Detour(AssetBundle __instance) { Object __result = null; AssetLoadingContext __state = null; if (Prefix(__instance, ref __result, ref __state)) { __result = _original(__instance); } Postfix(__instance, ref __result, ref __state); return __result; } } internal static class AssetBundle_returnMainAsset_Hook { private delegate Object OriginalMethod(AssetBundle __instance); private static OriginalMethod _original; private static bool Prepare(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return (object)AccessToolsShim.Method((assetBundle != null) ? assetBundle.ClrType : null, "returnMainAsset", new Type[1] { typeof(AssetBundle) }) != null; } private static MethodBase TargetMethod(object instance) { TypeContainer assetBundle = UnityTypes.AssetBundle; return AccessToolsShim.Method((assetBundle != null) ? assetBu