Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of balrond DualMastery v0.2.0
plugins/BalrondDualMastery.dll
Decompiled 2 days 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.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using HarmonyLib; using JetBrains.Annotations; using LitJson2; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: Guid("497EB368-9410-49A7-A098-9E3905D0DA35")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("DualWield")] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("DualWield")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] [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] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace BalrondDualWield { public class BalrondTranslator { public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>(); public static Dictionary<string, string> getLanguage(string language) { Dictionary<string, string> result = null; try { result = translations[language]; } catch (Exception) { } return result; } } internal static class DualWieldMath { private const float PrimaryAnimationRightWeight = 0.6f; private const float PrimaryAnimationLeftWeight = 0.4f; private static readonly HashSet<Player> SecondaryAttackPlayers = new HashSet<Player>(); internal static float GetDualSkillFactor(Player player) { return ((Object)(object)player != (Object)null) ? ((Character)player).GetSkillFactor((SkillType)874298) : 0f; } internal static float GetPrimaryOffhandDamageScale(Player player) { return 0.5f + 0.25f * GetDualSkillFactor(player); } internal static float GetSecondaryOffhandDamageScale(Player player) { return GetPrimaryOffhandDamageScale(player) + 0.5f; } internal static void SetSecondaryAttackState(Player player, bool active) { if (!((Object)(object)player == (Object)null)) { if (active) { SecondaryAttackPlayers.Add(player); } else { SecondaryAttackPlayers.Remove(player); } } } internal static bool IsMarkedSecondary(Player player) { return (Object)(object)player != (Object)null && SecondaryAttackPlayers.Contains(player); } internal static bool TryGetAttackIndexFromAnimator(Player player, out int attackIndex) { attackIndex = 1; if ((Object)(object)player == (Object)null || (Object)(object)((Character)player).m_animator == (Object)null) { return false; } AnimatorClipInfo[] currentAnimatorClipInfo = ((Character)player).m_animator.GetCurrentAnimatorClipInfo(0); if (currentAnimatorClipInfo == null || currentAnimatorClipInfo.Length == 0 || (Object)(object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip == (Object)null) { return false; } if (!Launch.AttackMap.TryGetValue(((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name, out var value)) { return false; } attackIndex = ClampAttackIndex(value); return true; } internal static int GetAttackIndexFromAttackState(Attack attack) { if (attack == null) { return 1; } return ClampAttackIndex(attack.m_currentAttackCainLevel + 1); } internal static bool IsSecondaryAttack(Player player, Attack attack) { if ((Object)(object)player == (Object)null || attack == null) { return false; } if (IsMarkedSecondary(player)) { return true; } if (TryGetAttackIndexFromAnimator(player, out var attackIndex) && attackIndex == 0) { return true; } if (((Humanoid)player).m_currentAttack == attack && !string.IsNullOrEmpty(attack.m_attackAnimation)) { string attackAnimation = attack.m_attackAnimation; if (Launch.AttackMap.TryGetValue(attackAnimation, out var value) && value == 0) { return true; } if (attackAnimation.IndexOf("secondary", StringComparison.OrdinalIgnoreCase) >= 0 || attackAnimation.IndexOf("jumpattack", StringComparison.OrdinalIgnoreCase) >= 0 || attackAnimation.IndexOf("alt", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } internal static float GetPrimaryCombinedSpeedFactor(Player player, int attackIndex) { ItemData item = (((Object)(object)player != (Object)null) ? ((Humanoid)player).m_rightItem : null); ItemData item2 = (((Object)(object)player != (Object)null) ? ((Humanoid)player).m_leftItem : null); float speed = GetBalancing(item, attackIndex).Speed; float speed2 = GetBalancing(item2, attackIndex).Speed; return speed * 0.6f + speed2 * 0.4f; } internal static float GetSecondaryCombinedSpeedFactor(Player player, int attackIndex) { return GetPrimaryCombinedSpeedFactor(player, attackIndex); } internal static float GetPrimaryStaminaCost(Player player, Attack attack) { return GetCombinedResourceCost(player, secondary: false, GetAttackStaminaCost, applySkillReduction: true); } internal static float GetSecondaryStaminaCost(Player player) { return GetCombinedResourceCost(player, secondary: true, GetAttackStaminaCost, applySkillReduction: true); } internal static float GetPrimaryHealthCost(Player player) { return GetCombinedResourceCost(player, secondary: false, GetAttackHealthCost, applySkillReduction: false); } internal static float GetSecondaryHealthCost(Player player) { return GetCombinedResourceCost(player, secondary: true, GetAttackHealthCost, applySkillReduction: false); } internal static float GetPrimaryEitrCost(Player player) { return GetCombinedResourceCost(player, secondary: false, GetAttackEitrCost, applySkillReduction: false); } internal static float GetSecondaryEitrCost(Player player) { return GetCombinedResourceCost(player, secondary: true, GetAttackEitrCost, applySkillReduction: false); } internal static float GetAttackStaminaCost(ItemData item, bool secondary) { Attack relevantAttack = GetRelevantAttack(item, secondary); if (relevantAttack == null) { return 0f; } return Mathf.Max(0f, relevantAttack.m_attackStamina); } internal static float GetAttackHealthCost(ItemData item, bool secondary) { Attack relevantAttack = GetRelevantAttack(item, secondary); if (relevantAttack == null) { return 0f; } return Mathf.Max(0f, relevantAttack.m_attackHealth); } internal static float GetAttackEitrCost(ItemData item, bool secondary) { Attack relevantAttack = GetRelevantAttack(item, secondary); if (relevantAttack == null) { return 0f; } return Mathf.Max(0f, relevantAttack.m_attackEitr); } internal static float SafeInverse(float value) { return (Math.Abs(value) <= 0.0001f) ? 1f : (1f / value); } internal static Launch.AnimationBalancing GetBalancingForItem(ItemData item, int attackIndex) { return GetBalancing(item, attackIndex); } private static float GetCombinedResourceCost(Player player, bool secondary, Func<ItemData, bool, float> getter, bool applySkillReduction) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || ((Humanoid)player).m_rightItem == null || ((Humanoid)player).m_leftItem == null) { return 0f; } ItemData rightItem = ((Humanoid)player).m_rightItem; ItemData leftItem = ((Humanoid)player).m_leftItem; float num = getter(rightItem, arg2: false); float num2 = getter(leftItem, arg2: false); float num3 = (secondary ? GetSecondaryOffhandDamageScale(player) : GetPrimaryOffhandDamageScale(player)); bool flag = num > 0f; bool flag2 = num2 > 0f; if (applySkillReduction) { if (flag) { num = ApplyWeaponSkillReduction(num, player, rightItem.m_shared.m_skillType); } if (flag2) { num2 = ApplyWeaponSkillReduction(num2, player, leftItem.m_shared.m_skillType); } } float num4 = ((flag && flag2) ? (num + num2 * num3) : (flag ? num : ((!flag2) ? 0f : (num2 * num3)))); if (applySkillReduction) { num4 = ApplyDualSkillReduction(num4, player); } if (secondary) { num4 += 5f; } return Mathf.Max(0f, num4); } private static Attack GetRelevantAttack(ItemData item, bool secondary) { if (item == null || item.m_shared == null) { return null; } if (secondary) { return item.m_shared.m_attack; } return item.m_shared.m_attack; } private static float ApplyWeaponSkillReduction(float cost, Player player, SkillType skillType) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return cost; } return cost - cost / 6f * ((Character)player).GetSkillFactor(skillType); } private static float ApplyDualSkillReduction(float cost, Player player) { if ((Object)(object)player == (Object)null) { return cost; } return cost - cost / 6f * ((Character)player).GetSkillFactor((SkillType)874298); } private static Launch.AnimationBalancing GetBalancing(ItemData item, int attackIndex) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (item == null || item.m_shared == null) { return GetFallbackBalancing(attackIndex); } if (Launch.BalancingMap.TryGetValue(item.m_shared.m_skillType, out Launch.AnimationBalancing[] value) && value != null && value.Length != 0) { return value[ClampAttackIndex(attackIndex)]; } return GetFallbackBalancing(attackIndex); } private static Launch.AnimationBalancing GetFallbackBalancing(int attackIndex) { int num = ClampAttackIndex(attackIndex); return new Launch.AnimationBalancing(1f, (num == 0) ? 20f : 15f); } private static int ClampAttackIndex(int attackIndex) { if (attackIndex < 0) { return 0; } if (attackIndex > 3) { return 3; } return attackIndex; } } [BepInPlugin("balrond.astafaraios.BalrondDualMastery", "BalrondDualMastery", "0.2.0")] public class Launch : BaseUnityPlugin { internal enum DualSkill { DualWield = 874298 } internal struct AnimationBalancing { public float Speed; public float Stamina; public AnimationBalancing(float speed, float stamina) { Speed = speed; Stamina = stamina; } } public const string PluginGUID = "balrond.astafaraios.BalrondDualMastery"; public const string PluginName = "BalrondDualMastery"; public const string PluginVersion = "0.2.0"; public static JsonLoader jsonLoader = new JsonLoader(); private Harmony harmony; internal const SkillType DualWieldSkillType = 874298; internal static AssetBundle AssetBundle; internal static readonly Dictionary<string, RuntimeAnimatorController> CustomRuntimeControllers = new Dictionary<string, RuntimeAnimatorController>(); internal static readonly Dictionary<string, AnimationClip> ExternalAnimations = new Dictionary<string, AnimationClip>(); internal static readonly Dictionary<string, Dictionary<string, string>> ReplacementMap = new Dictionary<string, Dictionary<string, string>>(); internal static readonly Dictionary<string, int> AttackMap = new Dictionary<string, int>(); private static readonly float skillFactor = 0.25f; private static readonly string skillName = "Dual Wield"; private static readonly string skillTooltip = "$tag_dualwield_bal_tooltip"; internal static readonly Dictionary<SkillType, AnimationBalancing[]> DefaultBalancing = new Dictionary<SkillType, AnimationBalancing[]> { { (SkillType)7, new AnimationBalancing[4] { new AnimationBalancing(0.6f, 40f), new AnimationBalancing(0.8f, 20f), new AnimationBalancing(0.7f, 20f), new AnimationBalancing(0.6f, 30f) } }, { (SkillType)3, new AnimationBalancing[4] { new AnimationBalancing(0.8f, 35f), new AnimationBalancing(1.2f, 14f), new AnimationBalancing(1.3f, 15f), new AnimationBalancing(1.5f, 15f) } }, { (SkillType)2, new AnimationBalancing[4] { new AnimationBalancing(1.4f, 32f), new AnimationBalancing(1.4f, 9f), new AnimationBalancing(1.4f, 9f), new AnimationBalancing(2f, 27f) } }, { (SkillType)1, new AnimationBalancing[4] { new AnimationBalancing(1f, 40f), new AnimationBalancing(1f, 15f), new AnimationBalancing(1f, 15f), new AnimationBalancing(1.2f, 20f) } } }; internal static readonly Dictionary<SkillType, AnimationBalancing[]> BalancingMap = new Dictionary<SkillType, AnimationBalancing[]>(); private void Awake() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown jsonLoader.loadJson(); InitializeAssets(); InitializeAttackMap(); InitializeReplacementMaps(); InitializeSkills(); InitializeBalancing(); harmony = new Harmony("balrond.astafaraios.BalrondDualMastery"); harmony.PatchAll(); } private static void InitializeAssets() { ExternalAnimations.Clear(); AssetBundle = GetAssetBundle("dwanimations"); LoadAnimation("Attack1External", "Attack1"); LoadAnimation("Attack2External", "Attack2"); LoadAnimation("Attack3External", "Attack3"); LoadAnimation("BlockExternal", "DWblock"); LoadAnimation("DualSpecial", "DWspecial"); } private static void LoadAnimation(string key, string asset) { AnimationClip val = AssetBundle.LoadAsset<AnimationClip>(asset); if ((Object)(object)val == (Object)null) { throw new Exception("Missing animation " + asset); } ExternalAnimations[key] = val; } private static void InitializeAttackMap() { AttackMap.Clear(); AttackMap["Attack1"] = 1; AttackMap["Attack2"] = 2; AttackMap["Attack3"] = 3; AttackMap["Sword-Attack-R4"] = 0; AttackMap["AxeAltAttack"] = 0; AttackMap["MaceAltAttack"] = 0; AttackMap["Knife JumpAttack"] = 0; AttackMap["axe_secondary"] = 0; AttackMap["AxeSecondaryAttack"] = 0; AttackMap["BattleAxeAltAttack"] = 0; } private static void InitializeReplacementMaps() { ReplacementMap.Clear(); ReplacementMap["Dual"] = BuildReplacementMap(); } private static Dictionary<string, string> BuildReplacementMap() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); dictionary["fight idle"] = "BlockExternal"; dictionary["Block idle"] = "BlockExternal"; foreach (KeyValuePair<string, int> item in AttackMap) { dictionary[item.Key] = ((item.Value == 0) ? "DualSpecial" : ("Attack" + item.Value + "External")); } return dictionary; } private static void InitializeSkills() { DualWieldSkills.AddNewSkill(DualSkill.DualWield, skillName, skillTooltip, skillFactor, DualWieldSkills.loadSprite("dualswords.png", 64, 64)); } private static void InitializeBalancing() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) BalancingMap.Clear(); foreach (KeyValuePair<SkillType, AnimationBalancing[]> item in DefaultBalancing) { AnimationBalancing[] array = new AnimationBalancing[item.Value.Length]; Array.Copy(item.Value, array, item.Value.Length); BalancingMap[item.Key] = array; } } internal static RuntimeAnimatorController MakeAnimatorOverrideController(Dictionary<string, string> replacement, RuntimeAnimatorController original) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown AnimatorOverrideController val = new AnimatorOverrideController(original); List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); AnimationClip[] animationClips = ((RuntimeAnimatorController)val).animationClips; foreach (AnimationClip val2 in animationClips) { if (replacement.TryGetValue(((Object)val2).name, out string value) && ExternalAnimations.TryGetValue(value, out AnimationClip value2) && (Object)(object)value2 != (Object)null) { AnimationClip val3 = Object.Instantiate<AnimationClip>(value2); ((Object)val3).name = ((Object)val2).name; list.Add(new KeyValuePair<AnimationClip, AnimationClip>(val2, val3)); } else { list.Add(new KeyValuePair<AnimationClip, AnimationClip>(val2, val2)); } } val.ApplyOverrides((IList<KeyValuePair<AnimationClip, AnimationClip>>)list); return (RuntimeAnimatorController)(object)val; } internal static void FastReplaceRuntimeAnimatorController(Player player, RuntimeAnimatorController replacement) { if (!((Object)(object)player == (Object)null) && !((Object)(object)((Character)player).m_animator == (Object)null) && !((Object)(object)replacement == (Object)null) && !((Object)(object)((Character)player).m_animator.runtimeAnimatorController == (Object)(object)replacement)) { ((Character)player).m_animator.runtimeAnimatorController = replacement; ((Character)player).m_animator.Update(Time.deltaTime); } } private static AssetBundle GetAssetBundle(string filename) { string filename2 = filename; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith(filename2, StringComparison.OrdinalIgnoreCase)); if (text == null) { throw new Exception("Missing embedded asset bundle"); } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { throw new Exception("Could not open embedded asset bundle stream"); } AssetBundle val = AssetBundle.LoadFromStream(stream); if ((Object)(object)val == (Object)null) { throw new Exception("Could not load asset bundle from stream"); } return val; } internal static bool IsOneHandedWeapon(ItemData item) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 return item != null && item.m_shared != null && (int)item.m_shared.m_itemType == 3; } internal static bool IsDualWieldingOneHandedWeapons(Player player) { return (Object)(object)player != (Object)null && IsOneHandedWeapon(((Humanoid)player).m_rightItem) && IsOneHandedWeapon(((Humanoid)player).m_leftItem); } internal static SharedData GetSharedDataFromHash(int hash) { if (hash == 0 || (Object)(object)ObjectDB.instance == (Object)null) { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash); if ((Object)(object)itemPrefab == (Object)null) { return null; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { return null; } return component.m_itemData.m_shared; } } public class JsonLoader { public string defaultPath = string.Empty; public void loadJson() { LoadTranslations(); justDefaultPath(); } public void justDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondDualMastery-translation/"); defaultPath = text; } public void createDefaultPath() { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondDualMastery-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("BalrondDualMastery: Folder already exists: " + text)); } defaultPath = text; } private string[] jsonFilePath(string folderName, string extension) { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "BalrondDualMastery-translation/"); if (!Directory.Exists(text)) { CreateFolder(text); } else { Debug.Log((object)("BalrondDualMastery: Folder already exists: " + text)); } string[] files = Directory.GetFiles(text, extension); Debug.Log((object)("BalrondDualMastery:" + folderName + " Json Files Found: " + files.Length)); return files; } private static void CreateFolder(string path) { try { Directory.CreateDirectory(path); Debug.Log((object)"BalrondDualMastery: Folder created successfully."); } catch (Exception ex) { Debug.Log((object)("BalrondDualMastery: Error creating folder: " + ex.Message)); } } private void LoadTranslations() { int num = 0; string[] array = jsonFilePath("Translation", "*.json"); foreach (string text in array) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string json = File.ReadAllText(text); JsonData jsonData = JsonMapper.ToObject(json); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string key in jsonData.Keys) { dictionary[key] = jsonData[key].ToString(); } if (dictionary != null) { BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary); Debug.Log((object)("BalrondDualMastery: Json Files Language: " + fileNameWithoutExtension)); num++; } else { Debug.LogError((object)("BalrondDualMastery: Loading FAILED file: " + text)); } } Debug.Log((object)("BalrondDualMastery: Translation JsonFiles Loaded: " + num)); } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] internal static class Patch_Attack_OnAttackTrigger { private struct StartAttackState { public Player Player; public ItemData RightItem; public Attack OriginalPrimaryAttack; public Attack OriginalSecondaryAttack; public bool ReplacedPrimaryAttack; public bool ReplacedSecondaryAttack; public bool IsSecondary; public float PendingHealthCost; public float PendingEitrCost; } [HarmonyPatch(typeof(Player), "GetRandomSkillFactor")] internal static class Patch_Player_GetRandomSkillFactor { private static bool Prefix(Player __instance, SkillType skill, ref float __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) if ((int)skill == 874298) { __result = 0.03f + ((Character)__instance).GetSkillFactor(skill) * 1.5f; return false; } return true; } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] internal static class Patch_Attack_GetAttackStamina { private static bool Prefix(Attack __instance, ref float __result) { Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null || !Launch.IsDualWieldingOneHandedWeapons(val)) { return true; } bool flag = DualWieldMath.IsSecondaryAttack(val, __instance); __result = (flag ? DualWieldMath.GetSecondaryStaminaCost(val) : DualWieldMath.GetPrimaryStaminaCost(val, __instance)); return false; } } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] internal static class Patch_Attack_DoMeleeAttack { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { MethodInfo quaternionEuler = AccessTools.DeclaredMethod(typeof(Quaternion), "Euler", new Type[3] { typeof(float), typeof(float), typeof(float) }, (Type[])null); FieldInfo attackAngleField = AccessTools.DeclaredField(typeof(Attack), "m_attackAngle"); List<CodeInstruction> instrs = new List<CodeInstruction>(instructions); int i = 0; while (i < instrs.Count) { if (i + 2 < instrs.Count && instrs[i].opcode == OpCodes.Neg && instrs[i + 2].opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instrs[i + 2], (MemberInfo)quaternionEuler)) { Label label = generator.DefineLabel(); yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Ldfld, (object)attackAngleField); yield return new CodeInstruction(OpCodes.Ldc_R4, (object)0f); yield return new CodeInstruction(OpCodes.Ble, (object)label); yield return new CodeInstruction(OpCodes.Neg, (object)null); instrs[i + 1].labels.Add(label); } else { yield return instrs[i]; } if (instrs[i].opcode == OpCodes.Ldfld && CodeInstructionExtensions.OperandIs(instrs[i], (MemberInfo)attackAngleField)) { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(Mathf), "Abs", new Type[1] { typeof(float) }, (Type[])null)); } int num = i + 1; i = num; } } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] internal static class Patch_Humanoid_StartAttack { private static bool Prefix(Humanoid __instance, bool secondaryAttack, ref bool __result, out StartAttackState __state) { __state = default(StartAttackState); Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || !Launch.IsDualWieldingOneHandedWeapons(val)) { return true; } ItemData rightItem = ((Humanoid)val).m_rightItem; if (rightItem == null || rightItem.m_shared == null) { return true; } float num = (secondaryAttack ? DualWieldMath.GetSecondaryHealthCost(val) : DualWieldMath.GetPrimaryHealthCost(val)); float num2 = (secondaryAttack ? DualWieldMath.GetSecondaryEitrCost(val) : DualWieldMath.GetPrimaryEitrCost(val)); if (((Character)val).GetHealth() <= num + 0.0001f) { __result = false; return false; } if (GetPlayerEitr(val) + 0.0001f < num2) { __result = false; return false; } __state.Player = val; __state.RightItem = rightItem; __state.PendingHealthCost = num; __state.PendingEitrCost = num2; __state.IsSecondary = secondaryAttack; if (secondaryAttack) { DualWieldMath.SetSecondaryAttackState(val, active: true); __state.OriginalSecondaryAttack = rightItem.m_shared.m_secondaryAttack; Attack attack = rightItem.m_shared.m_attack; if (attack != null) { Attack val2 = attack.Clone(); val2.m_attackHealth = 0f; val2.m_attackEitr = 0f; rightItem.m_shared.m_secondaryAttack = val2; __state.ReplacedSecondaryAttack = true; } } else { __state.OriginalPrimaryAttack = rightItem.m_shared.m_attack; if (__state.OriginalPrimaryAttack != null) { Attack val3 = __state.OriginalPrimaryAttack.Clone(); val3.m_attackHealth = 0f; val3.m_attackEitr = 0f; rightItem.m_shared.m_attack = val3; __state.ReplacedPrimaryAttack = true; } } return true; } private static void Postfix(Humanoid __instance, StartAttackState __state, bool __result) { if (__state.RightItem != null && __state.RightItem.m_shared != null) { if (__state.ReplacedPrimaryAttack) { __state.RightItem.m_shared.m_attack = __state.OriginalPrimaryAttack; } if (__state.ReplacedSecondaryAttack) { __state.RightItem.m_shared.m_secondaryAttack = __state.OriginalSecondaryAttack; } } if (!__result && (Object)(object)__state.Player != (Object)null) { DualWieldMath.SetSecondaryAttackState(__state.Player, active: false); } else if (__result && (Object)(object)__state.Player != (Object)null) { if (__state.PendingHealthCost > 0f) { UsePlayerHealth(__state.Player, __state.PendingHealthCost); } if (__state.PendingEitrCost > 0f) { UsePlayerEitr(__state.Player, __state.PendingEitrCost); } } } } private static float _rightSharedScale = 1f; private static float _leftSharedScale = 1f; private static SharedData _rightScaledShared; private static SharedData _leftScaledShared; private static readonly string[] SwappedAttackFields = new string[13] { "m_hitTerrain", "m_specialHitType", "m_specialHitSkill", "m_attackRange", "m_attackHeight", "m_attackRayWidth", "m_attackOffset", "m_damageMultiplier", "m_forceMultiplier", "m_staggerMultiplier", "m_lowerDamagePerHit", "m_resetChainIfHit", "m_hitPointtype" }; private static Dictionary<FieldInfo, object> SnapshotAttackFields(Attack attack) { Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>(); string[] swappedAttackFields = SwappedAttackFields; foreach (string text in swappedAttackFields) { FieldInfo fieldInfo = AccessTools.Field(typeof(Attack), text); if (fieldInfo != null) { dictionary[fieldInfo] = fieldInfo.GetValue(attack); } } return dictionary; } private static void CopyAttackFields(Attack source, Attack destination) { string[] swappedAttackFields = SwappedAttackFields; foreach (string text in swappedAttackFields) { FieldInfo fieldInfo = AccessTools.Field(typeof(Attack), text); if (fieldInfo != null) { fieldInfo.SetValue(destination, fieldInfo.GetValue(source)); } } } private static void RestoreAttackFields(Attack attack, Dictionary<FieldInfo, object> backup) { foreach (KeyValuePair<FieldInfo, object> item in backup) { item.Key.SetValue(attack, item.Value); } } private static void ApplySharedScale(SharedData shared, float factor) { if (shared != null && !(Math.Abs(factor - 1f) <= 0.0001f)) { ((DamageTypes)(ref shared.m_damages)).Modify(factor); shared.m_attackForce *= factor; shared.m_backstabBonus *= factor; } } private static float GetPlayerEitr(Player player) { if ((Object)(object)player == (Object)null) { return 0f; } MethodInfo methodInfo = AccessTools.Method(((object)player).GetType(), "GetEitr", (Type[])null, (Type[])null); if (methodInfo == null) { return 0f; } object obj = methodInfo.Invoke(player, null); return (obj is float) ? ((float)obj) : 0f; } private static void UsePlayerEitr(Player player, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f)) { MethodInfo methodInfo = AccessTools.Method(((object)player).GetType(), "UseEitr", new Type[1] { typeof(float) }, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(player, new object[1] { amount }); } } } private static void UsePlayerHealth(Player player, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f)) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "GetHealth", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Character), "SetHealth", new Type[1] { typeof(float) }, (Type[])null); if (!(methodInfo == null) && !(methodInfo2 == null)) { object obj = methodInfo.Invoke(player, null); float num = ((obj is float) ? ((float)obj) : 0f); float num2 = Mathf.Max(1f, num - amount); methodInfo2.Invoke(player, new object[1] { num2 }); } } } private static void Prefix(Attack __instance) { _rightSharedScale = 1f; _leftSharedScale = 1f; _rightScaledShared = null; _leftScaledShared = null; Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null || !Launch.IsDualWieldingOneHandedWeapons(val)) { return; } ItemData rightItem = ((Humanoid)val).m_rightItem; ItemData leftItem = ((Humanoid)val).m_leftItem; if (rightItem == null || leftItem == null) { return; } float leftSharedScale = (DualWieldMath.IsSecondaryAttack(val, __instance) ? DualWieldMath.GetSecondaryOffhandDamageScale(val) : DualWieldMath.GetPrimaryOffhandDamageScale(val)); _rightScaledShared = rightItem.m_shared; _leftScaledShared = leftItem.m_shared; _rightSharedScale = 1f; _leftSharedScale = leftSharedScale; Dictionary<FieldInfo, object> dictionary = null; Attack attack = leftItem.m_shared.m_attack; if (attack != null) { dictionary = SnapshotAttackFields(__instance); } ItemData weapon = __instance.m_weapon; float attackAngle = __instance.m_attackAngle; try { if (attack != null) { CopyAttackFields(attack, __instance); } __instance.m_attackAngle = 0f - __instance.m_attackAngle; __instance.m_weapon = leftItem; ApplySharedScale(leftItem.m_shared, _leftSharedScale); __instance.DoMeleeAttack(); } finally { ApplySharedScale(leftItem.m_shared, DualWieldMath.SafeInverse(_leftSharedScale)); if (dictionary != null) { RestoreAttackFields(__instance, dictionary); } __instance.m_weapon = weapon; __instance.m_attackAngle = attackAngle; } } private static void Postfix(Attack __instance) { Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val != (Object)null) { DualWieldMath.SetSecondaryAttackState(val, active: false); } _rightScaledShared = null; _leftScaledShared = null; _rightSharedScale = 1f; _leftSharedScale = 1f; } } [HarmonyPatch(typeof(Player), "Start")] internal static class Patch_Player_Start { private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Character)__instance).m_animator == (Object)null) && Launch.CustomRuntimeControllers.Count <= 0) { RuntimeAnimatorController runtimeAnimatorController = ((Character)__instance).m_animator.runtimeAnimatorController; if (!((Object)(object)runtimeAnimatorController == (Object)null)) { Launch.CustomRuntimeControllers["Original"] = Launch.MakeAnimatorOverrideController(new Dictionary<string, string>(), runtimeAnimatorController); Launch.CustomRuntimeControllers["Dual"] = Launch.MakeAnimatorOverrideController(Launch.ReplacementMap["Dual"], runtimeAnimatorController); } } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] internal static class Patch_Humanoid_EquipItem { private static bool CheckDualOneHandedWeaponEquip(Humanoid humanoid, ItemData item, bool triggerEquipEffects) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 Player val = (Player)(object)((humanoid is Player) ? humanoid : null); if ((Object)(object)val == (Object)null || item == null || item.m_shared == null) { return false; } if (((Humanoid)val).m_rightItem != null && ((Humanoid)val).m_rightItem.m_shared != null && (int)((Humanoid)val).m_rightItem.m_shared.m_itemType == 3 && (int)item.m_shared.m_skillType != 5) { if (((Humanoid)val).m_leftItem != null) { ((Humanoid)val).UnequipItem(((Humanoid)val).m_leftItem, triggerEquipEffects); } ((Humanoid)val).m_leftItem = item; return true; } return false; } private static void Prefix() { Patch_Humanoid_SetupEquipment.ManipulatingEquipment = true; } private static void Postfix() { Patch_Humanoid_SetupEquipment.ManipulatingEquipment = false; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> instrs = instructions.ToList(); int i = 0; while (i < instrs.Count) { yield return instrs[i]; if (i >= 4 && instrs[i - 4].opcode == OpCodes.Ldarg_1 && instrs[i - 1].opcode == OpCodes.Ldc_I4_3 && instrs[i].opcode == OpCodes.Bne_Un) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_2, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(Patch_Humanoid_EquipItem), "CheckDualOneHandedWeaponEquip", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Brtrue, instrs[i].operand); } int num = i + 1; i = num; } } } [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] internal static class Patch_Humanoid_UnequipAllItems { private static void Prefix() { Patch_Humanoid_SetupEquipment.ManipulatingEquipment = true; } private static void Postfix() { Patch_Humanoid_SetupEquipment.ManipulatingEquipment = false; } } [HarmonyPatch(typeof(Humanoid), "SetupEquipment")] internal static class Patch_Humanoid_SetupEquipment { internal static bool ManipulatingEquipment; private static void Prefix(Humanoid __instance) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && !ManipulatingEquipment && ((Humanoid)val).m_rightItem == null && ((Humanoid)val).m_leftItem != null && ((Humanoid)val).m_leftItem.m_shared != null && (int)((Humanoid)val).m_leftItem.m_shared.m_itemType == 3) { ItemData leftItem = ((Humanoid)val).m_leftItem; ((Humanoid)val).UnequipItem(((Humanoid)val).m_leftItem, false); ((Humanoid)val).m_rightItem = leftItem; ((Humanoid)val).m_rightItem.m_equipped = true; ((Humanoid)val).m_leftItem = null; } } } [HarmonyPatch(typeof(VisEquipment), "SetWeaponTrails")] internal static class Patch_VisEquipment_SetWeaponTrails { private static void Postfix(VisEquipment __instance, bool enabled) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.m_leftItemInstance == (Object)null) { return; } MeleeWeaponTrail[] componentsInChildren = __instance.m_leftItemInstance.GetComponentsInChildren<MeleeWeaponTrail>(); MeleeWeaponTrail[] array = componentsInChildren; foreach (MeleeWeaponTrail val in array) { if ((Object)(object)val != (Object)null) { val.Emit = enabled; } } } } [HarmonyPatch(typeof(VisEquipment), "AttachItem")] internal static class Patch_VisEquipment_AttachItem { private static void Postfix(VisEquipment __instance, Transform joint) { //IL_0053: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !((Object)(object)joint == (Object)null)) { if ((Object)(object)joint == (Object)(object)__instance.m_backMelee && joint.childCount > 1) { joint.GetChild(1).localPosition = new Vector3(-0.003f, 0f, 0.003f); joint.GetChild(1).localEulerAngles = new Vector3(0f, 80f, 0f); } if ((Object)(object)joint == (Object)(object)__instance.m_backTool && joint.childCount > 1) { joint.GetChild(1).localPosition = new Vector3(-0.0008f, -0.0052f, 0f); joint.GetChild(1).localEulerAngles = new Vector3(20f, 0f, 0f); } } } } [HarmonyPatch(typeof(ZSyncAnimation), "RPC_SetTrigger")] internal static class Patch_ZSyncAnimation_RPC_SetTrigger { private static void Prefix(ZSyncAnimation __instance, string name) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Invalid comparison between Unknown and I4 //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Invalid comparison between Unknown and I4 string name2 = name; if ((Object)(object)__instance == (Object)null || string.IsNullOrEmpty(name2)) { return; } Player component = ((Component)__instance).GetComponent<Player>(); if ((Object)(object)component == (Object)null || (Object)(object)((Humanoid)component).m_visEquipment == (Object)null) { return; } SharedData sharedDataFromHash = Launch.GetSharedDataFromHash(((Humanoid)component).m_visEquipment.m_currentRightItemHash); SharedData sharedDataFromHash2 = Launch.GetSharedDataFromHash(((Humanoid)component).m_visEquipment.m_currentLeftItemHash); if (HasAttack(sharedDataFromHash2) || HasAttack(sharedDataFromHash) || IsMappedDualAttackTrigger()) { string key = "Original"; if (sharedDataFromHash2 != null && sharedDataFromHash != null && (int)sharedDataFromHash2.m_itemType == 3 && (int)sharedDataFromHash.m_itemType == 3) { key = "Dual"; } if (Launch.CustomRuntimeControllers.TryGetValue(key, out RuntimeAnimatorController value)) { Launch.FastReplaceRuntimeAnimatorController(component, value); } } bool HasAttack(SharedData data) { if (data == null) { return false; } string animName2 = ((data.m_attack != null) ? data.m_attack.m_attackAnimation : null); string animName3 = ((data.m_secondaryAttack != null) ? data.m_secondaryAttack.m_attackAnimation : null); return HasAttackName(animName2) || HasAttackName(animName3); } bool HasAttackName(string animName) { return !string.IsNullOrEmpty(animName) && (name2 == animName || name2.StartsWith(animName)); } bool IsMappedDualAttackTrigger() { foreach (KeyValuePair<string, int> item in Launch.AttackMap) { if (name2 == item.Key || name2.StartsWith(item.Key)) { return true; } } return false; } } } [HarmonyPatch(typeof(CharacterAnimEvent), "CustomFixedUpdate")] internal static class Patch_CharacterAnimEvent_CustomFixedUpdate { [HarmonyPriority(300)] [UsedImplicitly] private static void Prefix(Character ___m_character, ref Animator ___m_animator) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown if ((Object)(object)___m_character == (Object)null || (Object)(object)___m_animator == (Object)null || !___m_character.IsPlayer() || !___m_character.InAttack() || (___m_animator.speed * 10000f % 10f >= 1f && ___m_animator.speed * 10000f % 10f <= 3f) || ___m_animator.speed <= 0.001f) { return; } Player val = (Player)___m_character; Attack currentAttack = ((Humanoid)val).m_currentAttack; if (currentAttack != null && Launch.IsDualWieldingOneHandedWeapons(val)) { if (!DualWieldMath.TryGetAttackIndexFromAnimator(val, out var attackIndex)) { attackIndex = DualWieldMath.GetAttackIndexFromAttackState(currentAttack); } float num = (DualWieldMath.IsSecondaryAttack(val, currentAttack) ? DualWieldMath.GetSecondaryCombinedSpeedFactor(val, attackIndex) : DualWieldMath.GetPrimaryCombinedSpeedFactor(val, attackIndex)); ___m_animator.speed = (float)Math.Round(___m_animator.speed * num, 3) + ___m_animator.speed % 0.0001f + 0.0002f; } } } public static class DualWieldSkills { private sealed class SkillDetails { public string SkillName; public string InternalSkillName; public SkillDef SkillDef; } [HarmonyPatch(typeof(Skills), "GetSkillDef")] private static class Patch_Skills_GetSkillDef { private static void Postfix(ref SkillDef __result, List<SkillDef> ___m_skills, SkillType type) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (__result != null) { return; } SkillDef skillDef = GetSkillDef(type); if (skillDef != null) { if (___m_skills != null && !___m_skills.Contains(skillDef)) { ___m_skills.Add(skillDef); } __result = skillDef; } } } [HarmonyPatch(typeof(Skills), "CheatRaiseSkill")] private static class Patch_Skills_CheatRaiseSkill { [HarmonyPrefix] private static bool Prefix(Skills __instance, string name, float value, Player ___m_player) { if (!TryGetSkillDetails(name, out int skillId, out SkillDetails details)) { return true; } Skill skill = __instance.GetSkill((SkillType)skillId); skill.m_level += value; skill.m_level = Mathf.Clamp(skill.m_level, 0f, 100f); if ((Object)(object)___m_player != (Object)null && skill.m_info != null) { ((Character)___m_player).Message((MessageType)1, "Skill increased " + details.SkillName + ": " + (int)skill.m_level, 0, skill.m_info.m_icon); } if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print("Skill " + details.SkillName + " = " + skill.m_level); } return false; } } [HarmonyPatch(typeof(Skills), "CheatResetSkill")] private static class Patch_Skills_CheatResetSkill { [HarmonyPrefix] private static bool Prefix(Skills __instance, string name) { if (!TryGetSkillDetails(name, out int skillId, out SkillDetails details)) { return true; } __instance.ResetSkill((SkillType)skillId); if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print("Skill " + details.SkillName + " reset"); } return false; } } [HarmonyPatch(typeof(Skills), "IsSkillValid")] private static class Patch_Skills_IsSkillValid { private static void Postfix(SkillType type, ref bool __result) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown if (!__result) { __result = SkillsById.ContainsKey((int)type); } } } private static readonly Dictionary<int, SkillDetails> SkillsById = new Dictionary<int, SkillDetails>(); private static readonly Dictionary<string, int> SkillIdsByInternalName = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); private static MethodInfo _loadImageMethod; private static bool _searchedLoadImageMethod; public static void AddNewSkill<T>(T skill, string skillName, string skillDescription, float skillIncreaseStep, Sprite skillIcon) where T : struct, IConvertible { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown int num = skill.ToInt32(CultureInfo.InvariantCulture); SkillType skill2 = (SkillType)(object)skill; SkillDetails skillDetails = new SkillDetails { SkillName = skillName, InternalSkillName = skill.ToString(), SkillDef = new SkillDef { m_description = skillDescription, m_icon = skillIcon, m_increseStep = skillIncreaseStep, m_skill = skill2 } }; SkillsById[num] = skillDetails; SkillIdsByInternalName[skillDetails.InternalSkillName] = num; } private static bool TryGetSkillDetails(SkillType skillType, out SkillDetails details) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected I4, but got Unknown return SkillsById.TryGetValue((int)skillType, out details); } private static bool TryGetSkillDetails(string internalName, out int skillId, out SkillDetails details) { skillId = 0; details = null; if (string.IsNullOrEmpty(internalName)) { return false; } if (!SkillIdsByInternalName.TryGetValue(internalName, out skillId)) { return false; } return SkillsById.TryGetValue(skillId, out details); } private static SkillDef GetSkillDef(SkillType skillType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown if (!TryGetSkillDetails(skillType, out SkillDetails details)) { return null; } if (Localization.instance != null) { Localization.instance.AddWord("skill_" + (int)skillType, details.SkillName); } return details.SkillDef; } private static byte[] ReadEmbeddedFileBytes(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); string text = null; for (int i = 0; i < manifestResourceNames.Length; i++) { if (manifestResourceNames[i].EndsWith(resourceName, StringComparison.OrdinalIgnoreCase)) { text = manifestResourceNames[i]; break; } } if (string.IsNullOrEmpty(text)) { throw new FileNotFoundException("Embedded resource not found: " + resourceName + "\nAvailable resources:\n" + string.Join("\n", manifestResourceNames)); } Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(text); if (manifestResourceStream == null) { throw new FileNotFoundException("Embedded resource stream not found: " + text); } try { MemoryStream memoryStream = new MemoryStream(); try { manifestResourceStream.CopyTo(memoryStream); return memoryStream.ToArray(); } finally { memoryStream.Dispose(); } } finally { manifestResourceStream.Dispose(); } } private static MethodInfo GetLoadImageMethod() { if (_searchedLoadImageMethod) { return _loadImageMethod; } _searchedLoadImageMethod = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (!(type == null)) { MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (method != null) { _loadImageMethod = method; return _loadImageMethod; } method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null); if (method != null) { _loadImageMethod = method; return _loadImageMethod; } } } return null; } private static bool TryLoadImage(Texture2D texture, byte[] data) { MethodInfo loadImageMethod = GetLoadImageMethod(); if (loadImageMethod == null) { throw new MissingMethodException("Could not find UnityEngine.ImageConversion.LoadImage at runtime."); } ParameterInfo[] parameters = loadImageMethod.GetParameters(); object obj = ((parameters.Length != 2) ? loadImageMethod.Invoke(null, new object[3] { texture, data, false }) : loadImageMethod.Invoke(null, new object[2] { texture, data })); return obj is bool && (bool)obj; } private static Texture2D LoadTexture(string name) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown byte[] data = ReadEmbeddedFileBytes("icons." + name); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); bool flag; try { flag = TryLoadImage(val, data); } catch { Object.Destroy((Object)(object)val); throw; } if (!flag) { Object.Destroy((Object)(object)val); throw new Exception("Failed to load texture from embedded resource: " + name); } return val; } public static Sprite LoadSprite(string name, int width, int height) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadTexture(name); return Sprite.Create(val, new Rect(0f, 0f, (float)width, (float)height), Vector2.zero); } public static Sprite loadSprite(string name, int width, int height) { return LoadSprite(name, width, height); } } [HarmonyPatch] internal static class TranslationPatches { [HarmonyPatch(typeof(FejdStartup), "SetupGui")] private class FejdStartup_SetupGUI { private static void Postfix() { string selectedLanguage = Localization.instance.GetSelectedLanguage(); Dictionary<string, string> translations = GetTranslations(selectedLanguage); AddTranslations(translations); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(Localization), "SetupLanguage")] private class Translation_SetupLanguage { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } [HarmonyPatch(typeof(Localization), "LoadCSV")] [HarmonyPriority(800)] private class Translation_LoadCSV { private static void Prefix(Localization __instance, string language) { Dictionary<string, string> translations = GetTranslations(language); AddTranslations(translations, __instance); } } private static Dictionary<string, string> GetTranslations(string language) { Dictionary<string, string> result = BalrondTranslator.getLanguage("English"); if (!string.Equals(language, "English", StringComparison.OrdinalIgnoreCase)) { Dictionary<string, string> language2 = BalrondTranslator.getLanguage(language); if (language2 != null) { result = language2; } else { Debug.Log((object)("BalrondDualMastery: Did not find translation file for '" + language + "', loading English")); } } return result; } private static void AddTranslations(Dictionary<string, string> translations, Localization localizationInstance = null) { if (translations == null) { Debug.LogWarning((object)"BalrondDualMastery: No translation file found!"); return; } if (localizationInstance != null) { foreach (KeyValuePair<string, string> translation in translations) { localizationInstance.AddWord(translation.Key, translation.Value); } return; } foreach (KeyValuePair<string, string> translation2 in translations) { Localization.instance.AddWord(translation2.Key, translation2.Value); } } } } namespace LitJson2 { internal enum JsonType { None, Object, Array, String, Int, Long, Double, Boolean } internal interface IJsonWrapper : IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable { bool IsArray { get; } bool IsBoolean { get; } bool IsDouble { get; } bool IsInt { get; } bool IsLong { get; } bool IsObject { get; } bool IsString { get; } bool GetBoolean(); double GetDouble(); int GetInt(); JsonType GetJsonType(); long GetLong(); string GetString(); void SetBoolean(bool val); void SetDouble(double val); void SetInt(int val); void SetJsonType(JsonType type); void SetLong(long val); void SetString(string val); string ToJson(); void ToJson(JsonWriter writer); } internal class JsonData : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable, IEquatable<JsonData> { private IList<JsonData> inst_array; private bool inst_boolean; private double inst_double; private int inst_int; private long inst_long; private IDictionary<string, JsonData> inst_object; private string inst_string; private string json; private JsonType type; private IList<KeyValuePair<string, JsonData>> object_list; public int Count => EnsureCollection().Count; public bool IsArray => type == JsonType.Array; public bool IsBoolean => type == JsonType.Boolean; public bool IsDouble => type == JsonType.Double; public bool IsInt => type == JsonType.Int; public bool IsLong => type == JsonType.Long; public bool IsObject => type == JsonType.Object; public bool IsString => type == JsonType.String; public ICollection<string> Keys { get { EnsureDictionary(); return inst_object.Keys; } } int ICollection.Count => Count; bool ICollection.IsSynchronized => EnsureCollection().IsSynchronized; object ICollection.SyncRoot => EnsureCollection().SyncRoot; bool IDictionary.IsFixedSize => EnsureDictionary().IsFixedSize; bool IDictionary.IsReadOnly => EnsureDictionary().IsReadOnly; ICollection IDictionary.Keys { get { EnsureDictionary(); IList<string> list = new List<string>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Key); } return (ICollection)list; } } ICollection IDictionary.Values { get { EnsureDictionary(); IList<JsonData> list = new List<JsonData>(); foreach (KeyValuePair<string, JsonData> item in object_list) { list.Add(item.Value); } return (ICollection)list; } } bool IJsonWrapper.IsArray => IsArray; bool IJsonWrapper.IsBoolean => IsBoolean; bool IJsonWrapper.IsDouble => IsDouble; bool IJsonWrapper.IsInt => IsInt; bool IJsonWrapper.IsLong => IsLong; bool IJsonWrapper.IsObject => IsObject; bool IJsonWrapper.IsString => IsString; bool IList.IsFixedSize => EnsureList().IsFixedSize; bool IList.IsReadOnly => EnsureList().IsReadOnly; object IDictionary.this[object key] { get { return EnsureDictionary()[key]; } set { if (!(key is string)) { throw new ArgumentException("The key has to be a string"); } JsonData value2 = ToJsonData(value); this[(string)key] = value2; } } object IOrderedDictionary.this[int idx] { get { EnsureDictionary(); return object_list[idx].Value; } set { EnsureDictionary(); JsonData value2 = ToJsonData(value); KeyValuePair<string, JsonData> keyValuePair = object_list[idx]; inst_object[keyValuePair.Key] = value2; KeyValuePair<string, JsonData> value3 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value2); object_list[idx] = value3; } } object IList.this[int index] { get { return EnsureList()[index]; } set { EnsureList(); JsonData value2 = ToJsonData(value); this[index] = value2; } } public JsonData this[string prop_name] { get { EnsureDictionary(); return inst_object[prop_name]; } set { EnsureDictionary(); KeyValuePair<string, JsonData> keyValuePair = new KeyValuePair<string, JsonData>(prop_name, value); if (inst_object.ContainsKey(prop_name)) { for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == prop_name) { object_list[i] = keyValuePair; break; } } } else { object_list.Add(keyValuePair); } inst_object[prop_name] = value; json = null; } } public JsonData this[int index] { get { EnsureCollection(); if (type == JsonType.Array) { return inst_array[index]; } return object_list[index].Value; } set { EnsureCollection(); if (type == JsonType.Array) { inst_array[index] = value; } else { KeyValuePair<string, JsonData> keyValuePair = object_list[index]; KeyValuePair<string, JsonData> value2 = new KeyValuePair<string, JsonData>(keyValuePair.Key, value); object_list[index] = value2; inst_object[keyValuePair.Key] = value; } json = null; } } public JsonData() { } public JsonData(bool boolean) { type = JsonType.Boolean; inst_boolean = boolean; } public JsonData(double number) { type = JsonType.Double; inst_double = number; } public JsonData(int number) { type = JsonType.Int; inst_int = number; } public JsonData(long number) { type = JsonType.Long; inst_long = number; } public JsonData(object obj) { if (obj is bool) { type = JsonType.Boolean; inst_boolean = (bool)obj; return; } if (obj is double) { type = JsonType.Double; inst_double = (double)obj; return; } if (obj is int) { type = JsonType.Int; inst_int = (int)obj; return; } if (obj is long) { type = JsonType.Long; inst_long = (long)obj; return; } if (obj is string) { type = JsonType.String; inst_string = (string)obj; return; } throw new ArgumentException("Unable to wrap the given object with JsonData"); } public JsonData(string str) { type = JsonType.String; inst_string = str; } public static implicit operator JsonData(bool data) { return new JsonData(data); } public static implicit operator JsonData(double data) { return new JsonData(data); } public static implicit operator JsonData(int data) { return new JsonData(data); } public static implicit operator JsonData(long data) { return new JsonData(data); } public static implicit operator JsonData(string data) { return new JsonData(data); } public static explicit operator bool(JsonData data) { if (data.type != JsonType.Boolean) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_boolean; } public static explicit operator double(JsonData data) { if (data.type != JsonType.Double) { throw new InvalidCastException("Instance of JsonData doesn't hold a double"); } return data.inst_double; } public static explicit operator int(JsonData data) { if (data.type != JsonType.Int) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_int; } public static explicit operator long(JsonData data) { if (data.type != JsonType.Long) { throw new InvalidCastException("Instance of JsonData doesn't hold an int"); } return data.inst_long; } public static explicit operator string(JsonData data) { if (data.type != JsonType.String) { throw new InvalidCastException("Instance of JsonData doesn't hold a string"); } return data.inst_string; } void ICollection.CopyTo(Array array, int index) { EnsureCollection().CopyTo(array, index); } void IDictionary.Add(object key, object value) { JsonData value2 = ToJsonData(value); EnsureDictionary().Add(key, value2); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>((string)key, value2); object_list.Add(item); json = null; } void IDictionary.Clear() { EnsureDictionary().Clear(); object_list.Clear(); json = null; } bool IDictionary.Contains(object key) { return EnsureDictionary().Contains(key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return ((IOrderedDictionary)this).GetEnumerator(); } void IDictionary.Remove(object key) { EnsureDictionary().Remove(key); for (int i = 0; i < object_list.Count; i++) { if (object_list[i].Key == (string)key) { object_list.RemoveAt(i); break; } } json = null; } IEnumerator IEnumerable.GetEnumerator() { return EnsureCollection().GetEnumerator(); } bool IJsonWrapper.GetBoolean() { if (type != JsonType.Boolean) { throw new InvalidOperationException("JsonData instance doesn't hold a boolean"); } return inst_boolean; } double IJsonWrapper.GetDouble() { if (type != JsonType.Double) { throw new InvalidOperationException("JsonData instance doesn't hold a double"); } return inst_double; } int IJsonWrapper.GetInt() { if (type != JsonType.Int) { throw new InvalidOperationException("JsonData instance doesn't hold an int"); } return inst_int; } long IJsonWrapper.GetLong() { if (type != JsonType.Long) { throw new InvalidOperationException("JsonData instance doesn't hold a long"); } return inst_long; } string IJsonWrapper.GetString() { if (type != JsonType.String) { throw new InvalidOperationException("JsonData instance doesn't hold a string"); } return inst_string; } void IJsonWrapper.SetBoolean(bool val) { type = JsonType.Boolean; inst_boolean = val; json = null; } void IJsonWrapper.SetDouble(double val) { type = JsonType.Double; inst_double = val; json = null; } void IJsonWrapper.SetInt(int val) { type = JsonType.Int; inst_int = val; json = null; } void IJsonWrapper.SetLong(long val) { type = JsonType.Long; inst_long = val; json = null; } void IJsonWrapper.SetString(string val) { type = JsonType.String; inst_string = val; json = null; } string IJsonWrapper.ToJson() { return ToJson(); } void IJsonWrapper.ToJson(JsonWriter writer) { ToJson(writer); } int IList.Add(object value) { return Add(value); } void IList.Clear() { EnsureList().Clear(); json = null; } bool IList.Contains(object value) { return EnsureList().Contains(value); } int IList.IndexOf(object value) { return EnsureList().IndexOf(value); } void IList.Insert(int index, object value) { EnsureList().Insert(index, value); json = null; } void IList.Remove(object value) { EnsureList().Remove(value); json = null; } void IList.RemoveAt(int index) { EnsureList().RemoveAt(index); json = null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { EnsureDictionary(); return new OrderedDictionaryEnumerator(object_list.GetEnumerator()); } void IOrderedDictionary.Insert(int idx, object key, object value) { string text = (string)key; JsonData value2 = (this[text] = ToJsonData(value)); KeyValuePair<string, JsonData> item = new KeyValuePair<string, JsonData>(text, value2); object_list.Insert(idx, item); } void IOrderedDictionary.RemoveAt(int idx) { EnsureDictionary(); inst_object.Remove(object_list[idx].Key); object_list.RemoveAt(idx); } private ICollection EnsureCollection() { if (type == JsonType.Array) { return (ICollection)inst_array; } if (type == JsonType.Object) { return (ICollection)inst_object; } throw new InvalidOperationException("The JsonData instance has to be initialized first"); } private IDictionary EnsureDictionary() { if (type == JsonType.Object) { return (IDictionary)inst_object; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a dictionary"); } type = JsonType.Object; inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); return (IDictionary)inst_object; } private IList EnsureList() { if (type == JsonType.Array) { return (IList)inst_array; } if (type != 0) { throw new InvalidOperationException("Instance of JsonData is not a list"); } type = JsonType.Array; inst_array = new List<JsonData>(); return (IList)inst_array; } private JsonData ToJsonData(object obj) { if (obj == null) { return null; } if (obj is JsonData) { return (JsonData)obj; } return new JsonData(obj); } private static void WriteJson(IJsonWrapper obj, JsonWriter writer) { if (obj == null) { writer.Write(null); } else if (obj.IsString) { writer.Write(obj.GetString()); } else if (obj.IsBoolean) { writer.Write(obj.GetBoolean()); } else if (obj.IsDouble) { writer.Write(obj.GetDouble()); } else if (obj.IsInt) { writer.Write(obj.GetInt()); } else if (obj.IsLong) { writer.Write(obj.GetLong()); } else if (obj.IsArray) { writer.WriteArrayStart(); foreach (object item in (IEnumerable)obj) { WriteJson((JsonData)item, writer); } writer.WriteArrayEnd(); } else { if (!obj.IsObject) { return; } writer.WriteObjectStart(); foreach (DictionaryEntry item2 in (IDictionary)obj) { writer.WritePropertyName((string)item2.Key); WriteJson((JsonData)item2.Value, writer); } writer.WriteObjectEnd(); } } public int Add(object value) { JsonData value2 = ToJsonData(value); json = null; return EnsureList().Add(value2); } public void Clear() { if (IsObject) { ((IDictionary)this).Clear(); } else if (IsArray) { ((IList)this).Clear(); } } public bool Equals(JsonData x) { if (x == null) { return false; } if (x.type != type) { return false; } return type switch { JsonType.None => true, JsonType.Object => inst_object.Equals(x.inst_object), JsonType.Array => inst_array.Equals(x.inst_array), JsonType.String => inst_string.Equals(x.inst_string), JsonType.Int => inst_int.Equals(x.inst_int), JsonType.Long => inst_long.Equals(x.inst_long), JsonType.Double => inst_double.Equals(x.inst_double), JsonType.Boolean => inst_boolean.Equals(x.inst_boolean), _ => false, }; } public JsonType GetJsonType() { return type; } public void SetJsonType(JsonType type) { if (this.type != type) { switch (type) { case JsonType.Object: inst_object = new Dictionary<string, JsonData>(); object_list = new List<KeyValuePair<string, JsonData>>(); break; case JsonType.Array: inst_array = new List<JsonData>(); break; case JsonType.String: inst_string = null; break; case JsonType.Int: inst_int = 0; break; case JsonType.Long: inst_long = 0L; break; case JsonType.Double: inst_double = 0.0; break; case JsonType.Boolean: inst_boolean = false; break; } this.type = type; } } public string ToJson() { if (json != null) { return json; } StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.Validate = false; WriteJson(this, jsonWriter); json = stringWriter.ToString(); return json; } public void ToJson(JsonWriter writer) { bool validate = writer.Validate; writer.Validate = false; WriteJson(this, writer); writer.Validate = validate; } public override string ToString() { return type switch { JsonType.Array => "JsonData array", JsonType.Boolean => inst_boolean.ToString(), JsonType.Double => inst_double.ToString(), JsonType.Int => inst_int.ToString(), JsonType.Long => inst_long.ToString(), JsonType.Object => "JsonData object", JsonType.String => inst_string, _ => "Uninitialized JsonData", }; } } internal class OrderedDictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private IEnumerator<KeyValuePair<string, JsonData>> list_enumerator; public object Current => Entry; public DictionaryEntry Entry { get { KeyValuePair<string, JsonData> current = list_enumerator.Current; return new DictionaryEntry(current.Key, current.Value); } } public object Key => list_enumerator.Current.Key; public object Value => list_enumerator.Current.Value; public OrderedDictionaryEnumerator(IEnumerator<KeyValuePair<string, JsonData>> enumerator) { list_enumerator = enumerator; } public bool MoveNext() { return list_enumerator.MoveNext(); } public void Reset() { list_enumerator.Reset(); } } internal class JsonException : ApplicationException { public JsonException() { } internal JsonException(ParserToken token) : base($"Invalid token '{token}' in input string") { } internal JsonException(ParserToken token, Exception inner_exception) : base($"Invalid token '{token}' in input string", inner_exception) { } internal JsonException(int c) : base($"Invalid character '{(char)c}' in input string") { } internal JsonException(int c, Exception inner_exception) : base($"Invalid character '{(char)c}' in input string", inner_exception) { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception inner_exception) : base(message, inner_exception) { } } internal struct PropertyMetadata { public MemberInfo Info; public bool IsField; public Type Type; } internal struct ArrayMetadata { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsArray { get { return is_array; } set { is_array = value; } } public bool IsList { get { return is_list; } set { is_list = value; } } } internal struct ObjectMetadata { private Type element_type; private bool is_dictionary; private IDictionary<string, PropertyMetadata> properties; public Type ElementType { get { if (element_type == null) { return typeof(JsonData); } return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary<string, PropertyMetadata> Properties { get { return properties; } set { properties = value; } } } internal delegate void ExporterFunc(object obj, JsonWriter writer); internal delegate void ExporterFunc<T>(T obj, JsonWriter writer); internal delegate object ImporterFunc(object input); internal delegate TValue ImporterFunc<TJson, TValue>(TJson input); internal delegate IJsonWrapper WrapperFactory(); internal class JsonMapper { private static int max_nesting_depth; private static IFormatProvider datetime_format; private static IDictionary<Type, ExporterFunc> base_exporters_table; private static IDictionary<Type, ExporterFunc> custom_exporters_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table; private static IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table; private static IDictionary<Type, ArrayMetadata> array_metadata; private static readonly object array_metadata_lock; private static IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops; private static readonly object conv_ops_lock; private static IDictionary<Type, ObjectMetadata> object_metadata; private static readonly object object_metadata_lock; private static IDictionary<Type, IList<PropertyMetadata>> type_properties; private static readonly object type_properties_lock; private static JsonWriter static_writer; private static readonly object static_writer_lock; static JsonMapper() { array_metadata_lock = new object(); conv_ops_lock = new object(); object_metadata_lock = new object(); type_properties_lock = new object(); static_writer_lock = new object(); max_nesting_depth = 100; array_metadata = new Dictionary<Type, ArrayMetadata>(); conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); object_metadata = new Dictionary<Type, ObjectMetadata>(); type_properties = new Dictionary<Type, IList<PropertyMetadata>>(); static_writer = new JsonWriter(); datetime_format = DateTimeFormatInfo.InvariantInfo; base_exporters_table = new Dictionary<Type, ExporterFunc>(); custom_exporters_table = new Dictionary<Type, ExporterFunc>(); base_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); custom_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>(); RegisterBaseExporters(); RegisterBaseImporters(); } private static void AddArrayMetadata(Type type) { if (array_metadata.ContainsKey(type)) { return; } ArrayMetadata value = default(ArrayMetadata); value.IsArray = type.IsArray; if (type.GetInterface("System.Collections.IList") != null) { value.IsList = true; } PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name != "Item")) { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(int)) { value.ElementType = propertyInfo.PropertyType; } } } lock (array_metadata_lock) { try { array_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddObjectMetadata(Type type) { if (object_metadata.ContainsKey(type)) { return; } ObjectMetadata value = default(ObjectMetadata); if (type.GetInterface("System.Collections.IDictionary") != null) { value.IsDictionary = true; } value.Properties = new Dictionary<string, PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.Name == "Item") { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == typeof(string)) { value.ElementType = propertyInfo.PropertyType; } } else { PropertyMetadata value2 = default(PropertyMetadata); value2.Info = propertyInfo; value2.Type = propertyInfo.PropertyType; value.Properties.Add(propertyInfo.Name, value2); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo fieldInfo in fields) { PropertyMetadata value3 = default(PropertyMetadata); value3.Info = fieldInfo; value3.IsField = true; value3.Type = fieldInfo.FieldType; value.Properties.Add(fieldInfo.Name, value3); } lock (object_metadata_lock) { try { object_metadata.Add(type, value); } catch (ArgumentException) { } } } private static void AddTypeProperties(Type type) { if (type_properties.ContainsKey(type)) { return; } IList<PropertyMetadata> list = new List<PropertyMetadata>(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name == "Item")) { PropertyMetadata item = default(PropertyMetadata); item.Info = propertyInfo; item.IsField = false; list.Add(item); } } FieldInfo[] fields = type.GetFields(); foreach (FieldInfo info in fields) { PropertyMetadata item2 = default(PropertyMetadata); item2.Info = info; item2.IsField = true; list.Add(item2); } lock (type_properties_lock) { try { type_properties.Add(type, list); } catch (ArgumentException) { } } } private static MethodInfo GetConvOp(Type t1, Type t2) { lock (conv_ops_lock) { if (!conv_ops.ContainsKey(t1)) { conv_ops.Add(t1, new Dictionary<Type, MethodInfo>()); } } if (conv_ops[t1].ContainsKey(t2)) { return conv_ops[t1][t2]; } MethodInfo method = t1.GetMethod("op_Implicit", new Type[1] { t2 }); lock (conv_ops_lock) { try { conv_ops[t1].Add(t2, method); return method; } catch (ArgumentException) { return conv_ops[t1][t2]; } } } private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd) { return null; } Type underlyingType = Nullable.GetUnderlyingType(inst_type); Type type = underlyingType ?? inst_type; if (reader.Token == JsonToken.Null) { if (inst_type.IsClass || underlyingType != null) { return null; } throw new JsonException($"Can't assign null to an instance of type {inst_type}"); } if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean) { Type type2 = reader.Value.GetType(); if (type.IsAssignableFrom(type2)) { return reader.Value; } if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type)) { ImporterFunc importerFunc = custom_importers_table[type2][type]; return importerFunc(reader.Value); } if (base_importers_table.ContainsKey(type2) && base_importers_table[type2].ContainsKey(type)) { ImporterFunc importerFunc2 = base_importers_table[type2][type]; return importerFunc2(reader.Value); } if (type.IsEnum) { return Enum.ToObject(type, reader.Value); } MethodInfo convOp = GetConvOp(type, type2); if (convOp != null) { return convOp.Invoke(null, new object[1] { reader.Value }); } throw new JsonException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}"); } object obj = null; if (reader.Token == JsonToken.ArrayStart) { AddArrayMetadata(inst_type); ArrayMetadata arrayMetadata = array_metadata[inst_type]; if (!arrayMetadata.IsArray && !arrayMetadata.IsList) { throw new JsonException($"Type {inst_type} can't act as an array"); } IList list; Type elementType; if (!arrayMetadata.IsArray) { list = (IList)Activator.CreateInstance(inst_type); elementType = arrayMetadata.ElementType; } else { list = new ArrayList(); elementType = inst_type.GetElementType(); } while (true) { object obj2 = ReadValue(elementType, reader); if (obj2 == null && reader.Token == JsonToken.ArrayEnd) { break; } list.Add(obj2); } if (arrayMetadata.IsArray) { int count = list.Count; obj = Array.CreateInstance(elementType, count); for (int i = 0; i < count; i++) { ((Array)obj).SetValue(list[i], i); } } else { obj = list; } } else if (reader.Token == JsonToken.ObjectStart) { AddObjectMetadata(type); ObjectMetadata objectMetadata = object_metadata[type]; obj = Activator.CreateInstance(type); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string text = (string)reader.Value; if (objectMetadata.Properties.ContainsKey(text)) { PropertyMetadata propertyMetadata = objectMetadata.Properties[text]; if (propertyMetadata.IsField) { ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader)); continue; } PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info; if (propertyInfo.CanWrite) { propertyInfo.SetValue(obj, ReadValue(propertyMetadata.Type, reader), null); } else { ReadValue(propertyMetadata.Type, reader); } } else if (!objectMetadata.IsDictionary) { if (!reader.SkipNonMembers) { throw new JsonException($"The type {inst_type} doesn't have the property '{text}'"); } ReadSkip(reader); } else { ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader)); } } } return obj; } private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) { reader.Read(); if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null) { return null; } IJsonWrapper jsonWrapper = factory(); if (reader.Token == JsonToken.String) { jsonWrapper.SetString((string)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Double) { jsonWrapper.SetDouble((double)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Int) { jsonWrapper.SetInt((int)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Long) { jsonWrapper.SetLong((long)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.Boolean) { jsonWrapper.SetBoolean((bool)reader.Value); return jsonWrapper; } if (reader.Token == JsonToken.ArrayStart) { jsonWrapper.SetJsonType(JsonType.Array); while (true) { IJsonWrapper jsonWrapper2 = ReadValue(factory, reader); if (jsonWrapper2 == null && reader.Token == JsonToken.ArrayEnd) { break; } jsonWrapper.Add(jsonWrapper2); } } else if (reader.Token == JsonToken.ObjectStart) { jsonWrapper.SetJsonType(JsonType.Object); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string key = (string)reader.Value; jsonWrapper[key] = ReadValue(factory, reader); } } return jsonWrapper; } private static void ReadSkip(JsonReader reader) { ToWrapper(() => new JsonMockWrapper(), reader); } private static void RegisterBaseExporters() { base_exporters_table[typeof(byte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((byte)obj)); }; base_exporters_table[typeof(char)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((char)obj)); }; base_exporters_table[typeof(DateTime)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToString((DateTime)obj, datetime_format)); }; base_exporters_table[typeof(decimal)] = delegate(object obj, JsonWriter writer) { writer.Write((decimal)obj); }; base_exporters_table[typeof(sbyte)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((sbyte)obj)); }; base_exporters_table[typeof(short)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((short)obj)); }; base_exporters_table[typeof(ushort)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToInt32((ushort)obj)); }; base_exporters_table[typeof(uint)] = delegate(object obj, JsonWriter writer) { writer.Write(Convert.ToUInt64((uint)obj)); }; base_exporters_table[typeof(ulong)] = delegate(object obj, JsonWriter writer) { writer.Write((ulong)obj); }; } private static void RegisterBaseImporters() { ImporterFunc importer = (object input) => Convert.ToByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(byte), importer); importer = (object input) => Convert.ToUInt64((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ulong), importer); importer = (object input) => Convert.ToSByte((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(sbyte), importer); importer = (object input) => Convert.ToInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(short), importer); importer = (object input) => Convert.ToUInt16((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(ushort), importer); importer = (object input) => Convert.ToUInt32((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(uint), importer); importer = (object input) => Convert.ToSingle((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(float), importer); importer = (object input) => Convert.ToDouble((int)input); RegisterImporter(base_importers_table, typeof(int), typeof(double), importer); importer = (object input) => Convert.ToDecimal((double)input); RegisterImporter(base_importers_table, typeof(double), typeof(decimal), importer); importer = (object input) => Convert.ToUInt32((long)input); RegisterImporter(base_importers_table, typeof(long), typeof(uint), importer); importer = (object input) => Convert.ToChar((string)input); RegisterImporter(base_importers_table, typeof(string), typeof(char), importer); importer = (object input) => Convert.ToDateTime((string)input, datetime_format); RegisterImporter(base_importers_table, typeof(string), typeof(DateTime), importer); } private static void RegisterImporter(IDictionary<Type, IDictionary<Type, ImporterFunc>> table, Type json_type, Type value_type, ImporterFunc importer) { if (!table.ContainsKey(json_type)) { table.Add(json_type, new Dictionary<Type, ImporterFunc>()); } table[json_type][value_type] = importer; } private static void WriteValue(object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) { throw new JsonException($"Max allowed object depth reached while trying to export from type {obj.GetType()}"); } if (obj == null) { writer.Write(null); return; } if (obj is IJsonWrapper) { if (writer_is_private) { writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); } else { ((IJsonWrapper)obj).ToJson(writer); } return; } if (obj is string) { writer.Write((string)obj); return; } if (obj is double) { writer.Write((double)obj); return; } if (obj is int) { writer.Write((int)obj); return; } if (obj is bool) { writer.Write((bool)obj); return; } if (obj is long) { writer.Write((long)obj); return; } if (obj is Array) { writer.WriteArrayStart(); foreach (object item in (Array)obj) { WriteValue(item, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IList) { writer.WriteArrayStart(); foreach (object item2 in (IList)obj) { WriteValue(item2, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IDictionary) { writer.WriteObjectStart(); foreach (DictionaryEntry item3 in (IDictionary)obj) { writer.WritePropertyName((string)item3.Key); WriteValue(item3.Value, writer, writer_is_private, depth + 1); } writer.WriteObjectEnd(); return; } Type type = obj.GetType(); if (custom_exporters_table.ContainsKey(type)) { ExporterFunc exporterFunc = custom_exporters_table[type]; exporterFunc(obj, writer); return; } if (base_exporters_table.ContainsKey(type)) { ExporterFunc exporterFunc2 = base_exporters_table[type]; exporterFunc2(obj, writer); return; } if (obj is Enum) { Type underlyingType = Enum.GetUnderlyingType(type); if (underlyingType == typeof(long) || underlyingType == typeof(uint) || underlyingType == typeof(ulong)) { writer.Write((ulong)obj); } else { writer.Write((int)obj); } return; } AddTypeProperties(type); IList<PropertyMetadata> list = type_properties[type]; writer.WriteObjectStart(); foreach (PropertyMetadata item4 in list) { if (item4.IsField) { writer.WritePropertyName(item4.Info.Name); WriteValue(((FieldInfo)item4.Info).GetValue(obj), writer, writer_is_private, depth + 1); continue; } PropertyInfo propertyInfo = (PropertyInfo)item4.Info; if (propertyInfo.CanRead) { writer.WritePropertyName(item4.Info.Name); WriteValue(propertyInfo.GetValue(obj, null), writer, writer_is_private, depth + 1); } } writer.WriteObjectEnd(); } public static string ToJson(object obj) { lock (static_writer_lock) { static_writer.Reset(); WriteValue(obj, static_writer, writer_is_private: true, 0); return static_writer.ToString(); } } public static void ToJson(object obj, JsonWriter writer) { WriteValue(obj, writer, writer_is_private: false, 0); } public static JsonData ToObject(JsonReader reader) { return (JsonData)ToWrapper(() => new JsonData(), reader); } public static JsonData ToObject(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (JsonData)ToWrapper(() => new JsonData(), reader2); } public static JsonData ToObject(string json) { return (JsonData)ToWrapper(() => new JsonData(), json); } public static T ToObject<T>(JsonReader reader) { return (T)ReadValue(typeof(T), reader); } public static T ToObject<T>(TextReader reader) { JsonReader reader2 = new JsonReader(reader); return (T)ReadValue(typeof(T), reader2); } public static T ToObject<T>(string json) { JsonReader reader = new JsonReader(json); return (T)ReadValue(typeof(T), reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, JsonReader reader) { return ReadValue(factory, reader); } public static IJsonWrapper ToWrapper(WrapperFactory factory, string json) { JsonReader reader = new JsonReader(json); return ReadValue(factory, reader); } public static void RegisterExporter<T>(ExporterFunc<T> exporter) { ExporterFunc value = delegate(object obj, JsonWriter writer) { exporter((T)obj, writer); }; custom_exporters_table[typeof(T)] = value; } public static void RegisterImporter<TJson, TValue>(ImporterFunc<TJson, TValue> importer) { ImporterFunc importer2 = (object input) => importer((TJson)input); RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), importer2); } public static void UnregisterExporters() { custom_exporters_table.Clear(); } public static void UnregisterImporters() { custom_importers_table.Clear(); } } internal class JsonMockWrapper : IJsonWrapper, IList, IOrderedDictionary, IDictionary, ICollection, IEnumerable { public bool IsArray => false; public bool IsBoolean => false; public bool IsDouble => false; public bool IsInt => false; public bool IsLong => false; public bool IsObject => false; public bool IsString => false; bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; object IList.this[int index] { get { return null; } set { } } int ICollection.Count => 0; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => null; bool IDictionary.IsFixedSize => true; bool IDictionary.IsReadOnly => true; ICollection IDictionary.Keys => null; ICollection IDictionary.Values => null; object IDictionary.this[object key] { get { return null; } set { } } object IOrderedDictionary.this[int idx] { get { return null; } set { } } public bool GetBoolean() { return false; } public double GetDouble() { return 0.0; } public int GetInt() { return 0; } public JsonType GetJsonType() { return JsonType.None; } public long GetLong() { return 0L; } public string GetString() { return ""; } public void SetBoolean(bool val) { } public void SetDouble(double val) { } public void SetInt(int val) { } public void SetJsonType(JsonType type) { } public void SetLong(long val) { } public void SetString(string val) { } public string ToJson() { return ""; } public void ToJson(JsonWriter writer) { } int IList.Add(object value) { return 0; } void IList.Clear() { } bool IList.Contains(object value) { return false; } int IList.IndexOf(object value) { return -1; } void IList.Insert(int i, object v) { } void IList.Remove(object value) { } void IList.RemoveAt(int index) { } void ICollection.CopyTo(Array array, int index) { } IEnumerator IEnumerable.GetEnumerator() { return null; } void IDictionary.Add(object k, object v) { } void IDictionary.Clear() { } bool IDictionary.Contains(object key) { return false; } void IDictionary.Remove(object key) { } IDictionaryEnumerator IDictionary.GetEnumerator() { return null; } IDictionaryEnumerator IOrderedDictionary.GetEnumerator() { return null; } void IOrderedDictionary.Insert(int i, object k, object v) { } void IOrderedDictionary.RemoveAt(int i) { } } internal enum JsonToken { None, ObjectStart, PropertyName, ObjectEnd, ArrayStart, ArrayEnd, Int, Long, Double, String, Boolean, Null } internal class JsonReader { private static IDictionary<int, IDictionary<int, int[]>> parse_table; private Stack<int> automaton_stack; private int current_input; private int current_symbol; private bool end_of_json; private bool end_of_input; private Lexer lexer; private bool parser_in_string; private bool parser_return; private bool read_started; private TextReader reader; private bool reader_is_owned; private bool skip_non_members; private object token_value; private JsonToken token; public bool AllowComments { get { return lexer.AllowComments; } set { lexer.AllowComments = value; } } public bool AllowSingleQuotedStrings { get { return lexer.AllowSingleQuotedStrings; } set { lexer.AllowSingleQuotedStrings = value; } } public bool SkipNonMembers { get { return skip_non_members; } set { skip_non_members = value; } } public bool EndOfInput => end_of_input; public bool EndOfJson => end_of_json; public JsonToken Token => token; public object Value => token_value; static JsonReader() { PopulateParseTable(); } public JsonReader(string json_text) : this(new StringReader(json_text), owned: true) { } public JsonReader(TextReader reader) : this(reader, owned: false) { } private JsonReader(TextReader reader, bool owned) { if (reader == null) { throw new ArgumentNullException("reader"); } parser_in_string = false; parser_return = false; read_started = false; automaton_stack = new Stack<int>(); automaton_stack.Push(65553); automaton_stack.Push(65543); lexer = new Lexer(reader); end_of_input = false; end_of_json = false; skip_non_members = true; this.reader = reader; reader_is_owned = owned; } private static void PopulateParseTable() { parse_table = new Dictionary<int, IDictionary<int, int[]>>(); TableAddRow(ParserToken.Array); TableAddCol(ParserToken.Array, 91, 91, 65549); TableAddRow(ParserToken.ArrayPrime); TableAddCol(ParserToken.ArrayPrime, 34, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 91, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 93, 93); TableAddCol(ParserToken.ArrayPrime, 123, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65537, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65538, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65539, 65550, 65551, 93); TableAddCol(ParserToken.ArrayPrime, 65540, 65550, 65551, 93); TableAddRow(ParserToken.Object); TableAddCol(ParserToken.Object, 123, 123, 65545); TableAddRow(ParserToken.ObjectPrime); TableAddCol(ParserToken.ObjectPrime, 34, 65546, 65547, 125); TableAddCol(ParserToken.ObjectPrime, 125, 125); TableAddRow(ParserToken.Pair); TableAddCol(ParserToken.Pair, 34, 65552, 58, 65550); TableAddRow(ParserToken.PairRest); TableAddCol(ParserToken.PairRest, 44, 44, 65546, 65547); TableAddCol(ParserToken.PairRest, 125, 65554); TableAddRow(ParserToken.String); TableAddCol(ParserToken.String, 34, 34, 65541, 34); TableAddRow(ParserToken.Text); TableAddCol(ParserToken.Text, 91, 65548); TableAddCol(ParserToken.Text, 123, 65544); TableAddRow(ParserToken.Value); TableAddCol(ParserToken.Value, 34, 65552); TableAddCol(ParserToken.Value, 91, 65548); TableAddCol(ParserToken.Value, 123, 65544); TableAddCol(ParserToken.Value, 65537, 65537); TableAddCol(ParserToken.Value, 65538, 65538); TableAddCol(ParserToken.Value, 65539, 65539); TableAddCol(ParserToken.Value, 65540, 65540); TableAddRow(ParserToken.ValueRest); TableA