Please disclose if any significant portion of your mod was created 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 MoreCrossbows v1.2.11
plugins\MoreCrossbows.dll
Decompiled 2 years 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.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Common; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using SimpleJson; using UnityEngine; [assembly: AssemblyFileVersion("1.2.11")] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright probablykory © 2024")] [assembly: AssemblyProduct("MoreCrossbows")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("https://thunderstore.io/c/valheim/p/probablykory/MoreCrossbows/")] [assembly: AssemblyTitle("MoreCrossbows")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("probablykory")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.11.0")] [module: <593790ff-8d27-4d5c-9a64-7845a4a6794d>RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<4c7d4c47-933b-4dae-9a1f-a51ceddfeed4>Embedded] internal sealed class <4c7d4c47-933b-4dae-9a1f-a51ceddfeed4>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<4c7d4c47-933b-4dae-9a1f-a51ceddfeed4>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class <593790ff-8d27-4d5c-9a64-7845a4a6794d>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <593790ff-8d27-4d5c-9a64-7845a4a6794d>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreCrossbows { public static class Extensions { private static HashSet<CustomRecipe> hashsetRecipes; private static Dictionary<string, CustomPrefab> prefabsDict; public static bool Remove(this ObjectDB instance, string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } GameObject itemPrefab = instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab != (Object)null) { instance.m_items.Remove(itemPrefab); instance.m_itemByHash.Remove(StringExtensionMethods.GetStableHashCode(((Object)itemPrefab).name)); return true; } return false; } public static Recipe GetRecipe(this List<Recipe> list, Recipe recipe) { int num = ObjectDB.instance.m_recipes.IndexOf(recipe); if (num > -1) { return list[num]; } string name = ((object)recipe).ToString(); return ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => name.Equals(((object)r).ToString()))); } public static bool Update(this CustomRecipe recipe, RecipeConfig newRecipe) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown if (hashsetRecipes == null) { hashsetRecipes = AccessTools.Field(typeof(ItemManager), "Recipes").GetValue(ItemManager.Instance) as HashSet<CustomRecipe>; Get.Plugin.LogDebugOnly("Recipes Hashset value retrieved: {hashsetRecipes}"); } Recipe recipe2 = ObjectDB.instance.m_recipes.GetRecipe(recipe.Recipe); if ((Object)(object)recipe2 == (Object)null) { if (hashsetRecipes != null && hashsetRecipes.Contains(recipe)) { IPlugin plugin = Get.Plugin; object obj; if (recipe == null) { obj = null; } else { Recipe recipe3 = recipe.Recipe; obj = ((recipe3 != null) ? ((Object)recipe3).name : null); } plugin.LogDebugOnly("Removing and re-adding recipe " + (string?)obj + " in ItemManager."); ItemManager.Instance.RemoveRecipe(recipe); ItemManager.Instance.AddRecipe(new CustomRecipe(newRecipe)); return true; } IPlugin plugin2 = Get.Plugin; object obj2; if (recipe == null) { obj2 = null; } else { Recipe recipe4 = recipe.Recipe; obj2 = ((recipe4 != null) ? ((Object)recipe4).name : null); } plugin2.LogError("Error updating recipe " + (string?)obj2 + ", did not find existing recipe in ObjectDB or ItemManager"); return false; } IPlugin plugin3 = Get.Plugin; object obj3; if (recipe == null) { obj3 = null; } else { Recipe recipe5 = recipe.Recipe; obj3 = ((recipe5 != null) ? ((Object)recipe5).name : null); } plugin3.LogDebugOnly("Updating recipe " + (string?)obj3 + " in place."); recipe2.m_amount = newRecipe.Amount; recipe2.m_minStationLevel = newRecipe.MinStationLevel; GameObject prefab = PrefabManager.Instance.GetPrefab(newRecipe.CraftingStation); recipe2.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); Get.Plugin.LogDebugOnly($"... setting cs to {recipe2.m_craftingStation}."); recipe2.m_resources = newRecipe.GetRequirements(); Requirement[] resources = recipe2.m_resources; foreach (Requirement val in resources) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)val.m_resItem).name.Replace("JVLmock_", "")); if ((Object)(object)itemPrefab != (Object)null) { val.m_resItem = itemPrefab.GetComponent<ItemDrop>(); } } if (hashsetRecipes != null) { hashsetRecipes.Remove(recipe); hashsetRecipes.Add(new CustomRecipe(recipe2, false, false)); } return true; } public static bool PrefabExists(this PrefabManager instance, string name) { bool result = false; if (string.IsNullOrEmpty(name)) { return result; } if (prefabsDict == null) { PropertyInfo propertyInfo = ((object)PrefabManager.Instance).GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic).FirstOrDefault((MemberInfo m) => m.Name == "Prefabs") as PropertyInfo; if (propertyInfo != null && propertyInfo.GetValue(PrefabManager.Instance) is Dictionary<string, CustomPrefab> dictionary) { prefabsDict = dictionary; } } if (prefabsDict != null) { result = prefabsDict.ContainsKey(name); } return result; } public static void ApplyToAll(this ItemDrop itemDrop, Action<ItemData> callback) { callback(itemDrop.m_itemData); string name = itemDrop.m_itemData.m_shared.m_name; Inventory[] source = (from c in Player.s_players.Select((Player p) => ((Humanoid)p).GetInventory()).Concat(from c in Object.FindObjectsOfType<Container>() select c.GetInventory()) where c != null select c).ToArray(); foreach (ItemData item in (from i in (from p in ObjectDB.instance.m_items select p.GetComponent<ItemDrop>() into c where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((Component)c).GetComponent<ZNetView>()) select c).Concat(ItemDrop.s_instances) select i.m_itemData).Concat(source.SelectMany((Inventory i) => i.GetAllItems()))) { if (item.m_shared.m_name == name) { callback(item); } } } public static object Cast(this Type Type, object data) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "data"); return Expression.Lambda(Expression.Block(Expression.Convert(Expression.Convert(parameterExpression, data.GetType()), Type)), parameterExpression).Compile().DynamicInvoke(data); } } internal class Feature { public bool RequiresUpdate { get; protected set; } public bool LoadedInGame { get; protected set; } public bool EnabledByDefault { get; set; } public string Name { get; set; } public string Category { get; set; } public string Description { get; set; } public FeatureType Type { get; set; } public string Table { get; set; } public int MinTableLevel { get; set; } = 1; public string Requirements { get; set; } public int Amount { get; set; } = 1; public List<string> DependencyNames { get; set; } public ConfigEntry<bool> EnabledConfigEntry { get; protected set; } public Entries Entries { get; protected set; } public Feature(string name) { Name = name; LoadedInGame = false; DependencyNames = new List<string>(); } public virtual bool Initialize() { return false; } public virtual bool Load() { return false; } public virtual bool Unload() { return false; } public virtual bool Update() { return false; } public virtual string FetchTableEntryValue() { string a = Entries?.Table?.Value; if (string.Equals(a, "Custom") && Entries?.TableCustomName != null) { return Entries.TableCustomName.Value; } return Table; } } internal class FeatureItem : Feature { private CustomItem _customItem; public new ItemEntries Entries { get; protected set; } public string AoePrefabName { get; set; } public string AssetPath { get; set; } public string Damages { get; set; } = string.Empty; public int Knockback { get; set; } public AmmunitionType AmmoType { get; set; } public FeatureItem(string name) : base(name) { } private void OnEntrySettingChanged(object sender, EventArgs e) { Get.Plugin.LogDebugOnly("OnEntrySettingChanged fired on feature " + base.Name); base.RequiresUpdate = true; } private void OnEnabledSettingChanged(object sender, EventArgs e) { Get.Plugin.LogDebugOnly("OnEnabledSettingChanged fired on feature " + base.Name); Entries.SetVisibility(base.EnabledConfigEntry.Value); base.RequiresUpdate = true; SharedDrawers.ReloadConfigDisplay(); } public override string FetchTableEntryValue() { string a = Entries?.Table?.Value; if (string.Equals(a, "Custom") && Entries?.TableCustomName != null) { return Entries.TableCustomName.Value; } return base.Table; } public override bool Initialize() { if (!string.IsNullOrEmpty(base.Category) && !string.IsNullOrEmpty(base.Description)) { base.EnabledConfigEntry = MoreCrossbows.Instance.Config(base.Category, "Enable" + base.Name, base.EnabledByDefault, base.Description); base.EnabledConfigEntry.SettingChanged += OnEnabledSettingChanged; Entries = ItemEntries.GetFromFeature(MoreCrossbows.Instance, this, base.EnabledConfigEntry.Value); Entries.AddSettingsChangedHandler(OnEntrySettingChanged); } return true; } public override bool Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown base.RequiresUpdate = false; RecipeConfig newRecipe = new RecipeConfig { Item = Entries.Name, CraftingStation = CraftingStations.GetInternalName(FetchTableEntryValue()), RepairStation = CraftingStations.GetInternalName(FetchTableEntryValue()), MinStationLevel = ((Entries != null) ? Entries.MinTableLevel.Value : base.MinTableLevel), Amount = ((Entries != null) ? Entries.Amount.Value : base.Amount), Requirements = RequirementsEntry.Deserialize(Entries?.Requirements?.Value ?? base.Requirements) }; IPlugin plugin = Get.Plugin; CustomItem customItem = _customItem; object obj; if (customItem == null) { obj = null; } else { ItemDrop itemDrop = customItem.ItemDrop; obj = ((itemDrop != null) ? ((Object)itemDrop).name : null); } plugin.LogDebugOnly("Updating recipe for " + (string?)obj); Get.Plugin.LogDebugOnly("... table: " + CraftingStations.GetInternalName(FetchTableEntryValue()) + " level " + ((Entries != null) ? Entries.MinTableLevel.Value : base.MinTableLevel)); Get.Plugin.LogDebugOnly("... reqs: " + ((Entries != null) ? Entries.Requirements.Value : base.Requirements)); _customItem.Recipe.Update(newRecipe); Get.Plugin.LogDebugOnly("Overwriting damages of " + base.Name + " with : " + Entries.Damages.Value); setDamage(DamagesDict.Deserialize(Entries.Damages.Value), AoePrefabName); return true; } public override bool Load() { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown Get.Plugin.LogDebugOnly("Loading item " + base.Name); ItemConfig val = new ItemConfig { CraftingStation = CraftingStations.GetInternalName(FetchTableEntryValue()), RepairStation = CraftingStations.GetInternalName(FetchTableEntryValue()), MinStationLevel = ((Entries != null) ? Entries.MinTableLevel.Value : base.MinTableLevel), Amount = ((Entries != null) ? Entries.Amount.Value : base.Amount), Requirements = RequirementsEntry.Deserialize(Entries?.Requirements?.Value ?? base.Requirements) }; _customItem = new CustomItem(MoreCrossbows.Instance.assetBundle, AssetPath, true, val); setDamage(DamagesDict.Deserialize((Entries != null) ? Entries.Damages.Value : Damages), AoePrefabName); _customItem.ItemDrop.m_itemData.m_shared.m_attackForce = Knockback; if (AmmoType == AmmunitionType.Arrow) { _customItem.ItemDrop.m_itemData.m_shared.m_ammoType = "$ammo_arrows"; } else if (AmmoType == AmmunitionType.Bolt) { _customItem.ItemDrop.m_itemData.m_shared.m_ammoType = "$ammo_bolts"; } ItemManager.Instance.AddItem(_customItem); base.RequiresUpdate = false; base.LoadedInGame = true; return true; } public override bool Unload() { Get.Plugin.LogDebugOnly("Unloading item " + base.Name); ItemManager.Instance.RemoveItem(base.Name); ObjectDB.instance.Remove(base.Name); base.LoadedInGame = false; base.RequiresUpdate = false; return true; } private void setDamage(Dictionary<string, int> dmgs, string aoePrefabName) { _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_damage = (dmgs.ContainsKey(DamageTypes.Damage) ? dmgs[DamageTypes.Damage] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_blunt = (dmgs.ContainsKey(DamageTypes.Blunt) ? dmgs[DamageTypes.Blunt] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_slash = (dmgs.ContainsKey(DamageTypes.Slash) ? dmgs[DamageTypes.Slash] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_pierce = (dmgs.ContainsKey(DamageTypes.Pierce) ? dmgs[DamageTypes.Pierce] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_chop = (dmgs.ContainsKey(DamageTypes.Chop) ? dmgs[DamageTypes.Chop] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_pickaxe = (dmgs.ContainsKey(DamageTypes.Pickaxe) ? dmgs[DamageTypes.Pickaxe] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_fire = (dmgs.ContainsKey(DamageTypes.Fire) ? dmgs[DamageTypes.Fire] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_frost = (dmgs.ContainsKey(DamageTypes.Frost) ? dmgs[DamageTypes.Frost] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_lightning = (dmgs.ContainsKey(DamageTypes.Lightning) ? dmgs[DamageTypes.Lightning] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_poison = (dmgs.ContainsKey(DamageTypes.Poison) ? dmgs[DamageTypes.Poison] : 0); _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_spirit = (dmgs.ContainsKey(DamageTypes.Spirit) ? dmgs[DamageTypes.Spirit] : 0); if (string.IsNullOrEmpty(aoePrefabName)) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab(aoePrefabName); if ((Object)(object)prefab != (Object)null) { Get.Plugin.LogDebugOnly("seting aoe dmg of " + ((Object)_customItem.ItemDrop).name); Aoe component = prefab.GetComponent<Aoe>(); if ((Object)(object)component != (Object)null) { float num = _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_frost / 3f; component.m_damage.m_frost = num * 2f; _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_frost = num; component.m_damage.m_fire = _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_fire; component.m_damage.m_lightning = _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_lightning; component.m_damage.m_poison = _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_poison; component.m_damage.m_spirit = _customItem.ItemDrop.m_itemData.m_shared.m_damages.m_spirit; } } } } internal class FeatureRecipe : Feature { public FeatureRecipe(string name) : base(name) { } private void OnEntrySettingChanged(object sender, EventArgs e) { Get.Plugin.LogDebugOnly("OnEntrySettingChanged fired on feature " + base.Name); base.RequiresUpdate = true; } private void OnEnabledSettingChanged(object sender, EventArgs e) { Get.Plugin.LogDebugOnly("OnEnabledSettingChanged fired on feature " + base.Name); base.Entries.SetVisibility(base.EnabledConfigEntry.Value); base.RequiresUpdate = true; SharedDrawers.ReloadConfigDisplay(); } public override bool Initialize() { base.EnabledConfigEntry = MoreCrossbows.Instance.Config(base.Category, "Enable" + base.Name, base.EnabledByDefault, base.Description); base.EnabledConfigEntry.SettingChanged += OnEnabledSettingChanged; base.Entries = Entries.GetFromFeature(MoreCrossbows.Instance, this, null, base.EnabledConfigEntry.Value); base.Entries.AddSettingsChangedHandler(OnEntrySettingChanged); return true; } public override bool Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown base.RequiresUpdate = false; RecipeConfig newRecipe = new RecipeConfig { Item = base.Entries.Name, CraftingStation = CraftingStations.GetInternalName(FetchTableEntryValue()), RepairStation = CraftingStations.GetInternalName(FetchTableEntryValue()), MinStationLevel = ((base.Entries != null) ? base.Entries.MinTableLevel.Value : base.MinTableLevel), Amount = ((base.Entries != null) ? base.Entries.Amount.Value : base.Amount), Requirements = RequirementsEntry.Deserialize(base.Entries?.Requirements?.Value ?? base.Requirements) }; CustomRecipe recipe = ItemManager.Instance.GetRecipe("CraftEarly" + base.Name); Get.Plugin.LogDebugOnly("Updating recipe " + base.Entries.Name); Get.Plugin.LogDebugOnly(("... reqs: " + base.Entries != null) ? base.Entries.Requirements.Value : base.Requirements); recipe.Update(newRecipe); base.RequiresUpdate = false; return true; } public override bool Load() { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown Get.Plugin.LogDebugOnly("Loading recipe for " + base.Name); RecipeConfig val = new RecipeConfig { Name = "CraftEarly" + base.Entries.Name, Item = base.Entries.Name, CraftingStation = CraftingStations.GetInternalName(FetchTableEntryValue()), RepairStation = CraftingStations.GetInternalName(FetchTableEntryValue()), MinStationLevel = base.Entries.MinTableLevel.Value, Amount = base.Entries.Amount.Value, Requirements = RequirementsEntry.Deserialize(base.Entries.Requirements.Value) }; ItemManager.Instance.AddRecipe(new CustomRecipe(val)); base.RequiresUpdate = false; base.LoadedInGame = true; return true; } public override bool Unload() { Get.Plugin.LogDebugOnly("Unloading recipe for " + base.Name); ItemManager.Instance.RemoveRecipe("CraftEarly" + base.Name); base.LoadedInGame = false; base.RequiresUpdate = false; return true; } } public enum FeatureType { Crossbow, Arrow, Bolt } public enum AmmunitionType { None, Arrow, Bolt } public static class DamageTypes { public static string Damage => "Damage"; public static string Blunt => "Blunt"; public static string Slash => "Slash"; public static string Pierce => "Pierce"; public static string Chop => "Chop"; public static string Pickaxe => "Pickaxe"; public static string Fire => "Fire"; public static string Frost => "Frost"; public static string Lightning => "Lightning"; public static string Poison => "Poison"; public static string Spirit => "Spirit"; public static string[] GetValues() { return new string[11] { Damage, Blunt, Slash, Pierce, Chop, Pickaxe, Fire, Frost, Lightning, Poison, Spirit }; } } public class AcceptableKeysString : AcceptableValueBase { public virtual string[] AcceptableKeys { get; } public AcceptableKeysString(params string[] acceptableKeys) : base(typeof(string)) { if (acceptableKeys == null) { throw new ArgumentNullException("acceptableValues"); } if (acceptableKeys.Length == 0) { throw new ArgumentException("At least one acceptable key is needed", "AcceptableKeys"); } AcceptableKeys = acceptableKeys; } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { if (value is string) { return !string.IsNullOrEmpty((string)value); } return false; } public override string ToDescriptionString() { return "# Acceptable keys: " + string.Join(", ", AcceptableKeys.Select((string x) => x.ToString()).ToArray()); } } public static class DamagesDict { public static Dictionary<string, int> Deserialize(string dmgs) { if (string.IsNullOrEmpty(dmgs)) { return null; } return dmgs.Split(new char[1] { ',' }).Select(delegate(string d) { string[] array = d.Split(new char[1] { ':' }); int result; int result2; return (array.Length > 1) ? new KeyValuePair<string, int>(array[0], (!int.TryParse(array[1], out result)) ? 1 : result) : new KeyValuePair<string, int>("Damage", (!int.TryParse(array[0], out result2)) ? 1 : result2); }).ToDictionary((KeyValuePair<string, int> kvp) => kvp.Key, (KeyValuePair<string, int> kvp) => kvp.Value); } public static string Serialize(Dictionary<string, int> dmgs) { return string.Join(",", dmgs.Select((KeyValuePair<string, int> d) => $"{d.Key}:{d.Value}")); } } internal class Entries { public static Dictionary<ConfigurationManagerAttributes, Entries> SavedAttributes = new Dictionary<ConfigurationManagerAttributes, Entries>(); private static AcceptableValueList<string> AcceptableTableValues = new AcceptableValueList<string>(CraftingStations.GetAcceptableValueList().AcceptableValues.Concat(new string[1] { "Custom" }).ToArray()); protected bool visible = true; private Action<object, EventArgs> _action; public string Name { get; set; } = string.Empty; public ConfigEntry<string> Table { get; set; } public ConfigEntry<string> TableCustomName { get; set; } public ConfigEntry<int> MinTableLevel { get; set; } public ConfigEntry<int> Amount { get; set; } public ConfigEntry<string> Requirements { get; set; } public static bool IsTableCustom(string table) { string value; return !CraftingStations.GetNames().TryGetValue(table, out value); } public static ConfigurationManagerAttributes GetAttribute(Entries entries, bool isAdminOnly = true, bool isBrowsable = true, Action<ConfigEntryBase> customDrawer = null) { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { Browsable = isBrowsable, IsAdminOnly = isAdminOnly, CustomDrawer = customDrawer }; SavedAttributes.Add(val, entries); return val; } public static void UpdateBrowsable() { foreach (KeyValuePair<ConfigurationManagerAttributes, Entries> savedAttribute in SavedAttributes) { savedAttribute.Key.Browsable = savedAttribute.Value.visible; } Get.Plugin.LogDebugOnly("UpdateBrowsable called."); foreach (Entries item in SavedAttributes.Values.Distinct()) { object? obj = ((ConfigEntryBase)item.TableCustomName).Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes); ConfigurationManagerAttributes val = (ConfigurationManagerAttributes)((obj is ConfigurationManagerAttributes) ? obj : null); if (val != null) { val.Browsable = IsTableCustom(item.Table.Value) && item.visible; IPlugin plugin = Get.Plugin; string[] obj2 = new string[5] { item.Name, ": ", item.Table.Value, ", browsable: ", null }; bool? browsable = val.Browsable; obj2[4] = browsable.ToString(); plugin.LogDebugOnly(string.Concat(obj2)); } } } public static Entries GetFromFeature(IPlugin instance, Feature config, Entries entries = null, bool visible = true) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown bool hasUpgrades = config.Type == FeatureType.Crossbow; if (entries == null) { entries = new Entries(); } entries.visible = visible; entries.Name = config.Name; entries.Table = instance.Config(entries.Name, "Table", config.Table, new ConfigDescription("Crafting station where " + entries.Name + " is available.", (AcceptableValueBase)(object)AcceptableTableValues, new object[1] { GetAttribute(entries, isAdminOnly: true, visible) })); entries.TableCustomName = instance.Config(entries.Name, "Table (Custom Name)", IsTableCustom(config.Table) ? config.Table : "", new ConfigDescription("If custom, the name of the crafting station where " + entries.Name + " is available.", (AcceptableValueBase)null, new object[1] { GetAttribute(entries, isAdminOnly: true, IsTableCustom(config.Table) && visible) })); entries.MinTableLevel = instance.Config(entries.Name, "Table Level", config.MinTableLevel, new ConfigDescription("Level of crafting station required to craft " + entries.Name + ".", (AcceptableValueBase)null, new object[1] { GetAttribute(entries, entries.visible) })); entries.Amount = instance.Config(entries.Name, "Amount", config.Amount, new ConfigDescription("The amount of " + entries.Name + " created.", (AcceptableValueBase)null, new object[1] { GetAttribute(entries, entries.visible) })); entries.Requirements = instance.Config(entries.Name, "Requirements", config.Requirements, new ConfigDescription("The required items to craft " + entries.Name + ".", (AcceptableValueBase)(object)new AcceptableValueConfigNote("You must use valid spawn item codes."), new object[1] { GetAttribute(entries, entries.visible, isBrowsable: true, SharedDrawers.DrawReqConfigTable(hasUpgrades)) })); entries.Table.SettingChanged += OnTableSettingChanged; return entries; } private static void OnTableSettingChanged(object sender, EventArgs e) { UpdateBrowsable(); SharedDrawers.ReloadConfigDisplay(); } public void SetVisibility(bool visible) { this.visible = visible; UpdateBrowsable(); } protected void OnSettingChanged(object sender, EventArgs e) { if (_action != null) { _action(sender, e); } } public virtual void AddSettingsChangedHandler(Action<object, EventArgs> action) { _action = action; Table.SettingChanged += OnSettingChanged; MinTableLevel.SettingChanged += OnSettingChanged; Amount.SettingChanged += OnSettingChanged; Requirements.SettingChanged += OnSettingChanged; } public virtual void RemoveSettingsChangedHandler() { Table.SettingChanged -= OnSettingChanged; MinTableLevel.SettingChanged -= OnSettingChanged; Amount.SettingChanged -= OnSettingChanged; Requirements.SettingChanged -= OnSettingChanged; _action = null; } } internal class ItemEntries : Entries { public ConfigEntry<string> Damages { get; set; } public override void AddSettingsChangedHandler(Action<object, EventArgs> action) { base.AddSettingsChangedHandler(action); Damages.SettingChanged += base.OnSettingChanged; } public override void RemoveSettingsChangedHandler() { base.RemoveSettingsChangedHandler(); Damages.SettingChanged -= base.OnSettingChanged; } public static ItemEntries GetFromFeature(IPlugin instance, FeatureItem config, bool visible = true) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown ItemEntries entries = new ItemEntries(); entries = (ItemEntries)Entries.GetFromFeature(instance, config, entries, visible); entries.Damages = instance.Config(entries.Name, "Damages", config.Damages, new ConfigDescription("The damage done by " + entries.Name + ".", (AcceptableValueBase)(object)new AcceptableKeysString(DamageTypes.GetValues()), new object[1] { Entries.GetAttribute(entries, isAdminOnly: true, entries.visible, DamagesEntry.DrawDamagesConfigTable()) })); return entries; } } public class DamagesConfig { public string Prefab; public int Duration; } public static class DamagesEntry { public static DamagesConfig[] Deserialize(string dmgs) { return dmgs.Split(new char[1] { ',' }).Select(delegate(string r) { string[] array = r.Split(new char[1] { ':' }); int result; return new DamagesConfig { Prefab = array[0], Duration = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result) }; }).ToArray(); } public static string Serialize(DamagesConfig[] dmgs) { return string.Join(",", dmgs.Select((DamagesConfig r) => $"{r.Prefab}:{r.Duration}")); } public static Action<ConfigEntryBase> DrawDamagesConfigTable() { return delegate(ConfigEntryBase cfg) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown List<DamagesConfig> list = new List<DamagesConfig>(); bool flag = false; int rightColumnWidth = SharedDrawers.GetRightColumnWidth(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); foreach (DamagesConfig item in Deserialize((string)cfg.BoxedValue).ToList()) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = GUILayout.TextField(item.Prefab, new GUIStyle(GUI.skin.textField) { fixedWidth = rightColumnWidth - 56 - 21 - 21 - 9 }, Array.Empty<GUILayoutOption>()); string text2 = (string.IsNullOrEmpty(text) ? item.Prefab : text); flag = flag || text2 != item.Prefab; int num = item.Duration; if (int.TryParse(GUILayout.TextField(num.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 56f }, Array.Empty<GUILayoutOption>()), out var result) && result != num) { num = result; flag = true; } if (GUILayout.Button("x", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; } else { list.Add(new DamagesConfig { Prefab = text2, Duration = num }); } if (GUILayout.Button("+", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; list.Add(new DamagesConfig { Prefab = "<Damage Type>", Duration = 120 }); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = Serialize(list.ToArray()); } }; } } [Flags] public enum VisualEffectCondition : uint { IsSkill = 0xFFFu, Swords = 1u, Knives = 2u, Clubs = 3u, Polearms = 4u, Spears = 5u, Blocking = 6u, Axes = 7u, Bows = 8u, Unarmed = 0xBu, Pickaxes = 0xCu, WoodCutting = 0xDu, Crossbows = 0xEu, IsItem = 0xFF000u, Helmet = 0x6000u, Chest = 0x7000u, Legs = 0xB000u, Hands = 0xC000u, Shoulder = 0x11000u, Tool = 0x13000u, GenericExtraAttributes = 0xFF000000u, Blackmetal = 0x40000000u, TwoHanded = 0x80000000u, SpecificExtraAttributes = 0xF00000u, Hammer = 0x113000u, Hoe = 0x213000u, Buckler = 0x100006u, Towershield = 0x200006u, FineWoodBow = 0x100008u, BowHuntsman = 0x200008u, BowDraugrFang = 0x300008u, Arbalest = 0x10000Eu, CrossbowWood = 0x20000Eu, CrossbowBronze = 0x30000Eu, CrossbowIron = 0x40000Eu, CrossbowSilver = 0x50000Eu, CrossbowBlackmetal = 0x60000Eu, PickaxeIron = 0x10000Cu, Club = 0x100003u } public static class JewelcraftingPatches { private static FieldInfo effectPrefabsByTypeInfo; private static Type vecType; public static void Initialize(Harmony harmony, BaseUnityPlugin jewelcrafting) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown if (harmony == null || (Object)(object)jewelcrafting == (Object)null) { throw new ArgumentNullException("Attempted to initialize without harmony, jewelcrafting or both."); } Assembly assembly = ((object)jewelcrafting).GetType().Assembly; MethodInfo method = assembly.GetType("Jewelcrafting.GemEffects.VisualEffects").GetMethod("prefabDict"); MethodInfo method2 = typeof(JewelcraftingPatches).GetMethod("VisualEffectsPrefabDictPostfix", BindingFlags.Static | BindingFlags.NonPublic); if (method != null && method2 != null) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Get.Plugin.LogWarning($"Found Jewelcrafting but unable to patch. method = {method}, postfix = {method2}"); } List<string[]> list = new List<string[]>(); list.Add(new string[3] { "Perfect_Yellow_Socket", VisualEffectCondition.CrossbowIron.ToString(), "jc_echo_ironxbow" }); list.Add(new string[3] { "Perfect_Red_Socket", VisualEffectCondition.CrossbowIron.ToString(), "jc_endlessarrows_ironxbow" }); list.Add(new string[3] { "Perfect_Purple_Socket", VisualEffectCondition.CrossbowIron.ToString(), "jc_masterarcher_ironxbow" }); list.Add(new string[3] { "Perfect_Green_Socket", VisualEffectCondition.CrossbowIron.ToString(), "jc_necromancer_ironxbow" }); list.Add(new string[3] { "Perfect_Yellow_Socket", VisualEffectCondition.CrossbowSilver.ToString(), "jc_echo_silverxbow" }); list.Add(new string[3] { "Perfect_Red_Socket", VisualEffectCondition.CrossbowSilver.ToString(), "jc_endlessarrows_silverxbow" }); list.Add(new string[3] { "Perfect_Purple_Socket", VisualEffectCondition.CrossbowSilver.ToString(), "jc_masterarcher_silverxbow" }); list.Add(new string[3] { "Perfect_Green_Socket", VisualEffectCondition.CrossbowSilver.ToString(), "jc_necromancer_silverxbow" }); list.Add(new string[3] { "Perfect_Yellow_Socket", VisualEffectCondition.CrossbowBlackmetal.ToString(), "jc_echo_blackmetalxbow" }); list.Add(new string[3] { "Perfect_Red_Socket", VisualEffectCondition.CrossbowBlackmetal.ToString(), "jc_endlessarrows_blackmetalxbow" }); list.Add(new string[3] { "Perfect_Purple_Socket", VisualEffectCondition.CrossbowBlackmetal.ToString(), "jc_masterarcher_blackmetalxbow" }); list.Add(new string[3] { "Perfect_Green_Socket", VisualEffectCondition.CrossbowBlackmetal.ToString(), "jc_necromancer_blackmetalxbow" }); List<string[]> toLoad = list; Type? obj = assembly?.GetType("Jewelcrafting.GemEffects.VisualEffects"); if (vecType == null) { vecType = assembly?.GetType("Jewelcrafting.VisualEffectCondition"); } if ((obj?.GetField("attachEffectPrefabs", BindingFlags.Static | BindingFlags.Public))?.GetValue(null) is IDictionary effectPrefabs) { LoadPrefabs(effectPrefabs, toLoad); } else { Get.Plugin.LogDebugOnly("Unable to invoke attachEffectPrefabs, not found."); } } private static void LoadPrefabs(IDictionary effectPrefabs, List<string[]> toLoad) { foreach (string[] item in toLoad) { string text = item[0]; string text2 = item[2]; VisualEffectCondition visualEffectCondition = (VisualEffectCondition)Enum.Parse(typeof(VisualEffectCondition), item[1]); GameObject val = MoreCrossbows.Instance.assetBundle.LoadAsset<GameObject>(text2); if ((Object)(object)val == (Object)null) { Get.Plugin.LogWarning("Prefab " + text2 + " did not load correctly"); } if (effectPrefabs.Contains(text)) { if (effectPrefabs[text] is IDictionary dictionary && !dictionary.Contains(vecType.Cast(visualEffectCondition))) { Get.Plugin.LogDebugOnly($"Adding: {visualEffectCondition} {val} to effectPrefabs[{text}]"); dictionary.Add(vecType.Cast(visualEffectCondition), val); } else { Get.Plugin.LogDebugOnly($"effectPrefabs[{text}] already contains a {visualEffectCondition} key, skipping."); } continue; } Get.Plugin.LogWarning("attachEffectPrefabs does not contain " + text + " key; Aborting."); break; } } private static void VisualEffectsPrefabDictPostfix(ref Dictionary<string, GameObject[]> __result, SharedData shared) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if (__result == null || (int)shared.m_skillType != 14) { return; } VisualEffectCondition visualEffectCondition = SkillKey(shared); int num = ((__result != null) ? __result.Count : 0); if (effectPrefabsByTypeInfo == null || vecType == null) { Assembly obj = ((object)MoreCrossbows.Instance.jewelcrafting)?.GetType().Assembly; Type type = obj?.GetType("Jewelcrafting.GemEffects.VisualEffects"); vecType = obj?.GetType("Jewelcrafting.VisualEffectCondition"); effectPrefabsByTypeInfo = type?.GetField("effectPrefabsByType", BindingFlags.Static | BindingFlags.NonPublic); } if (effectPrefabsByTypeInfo?.GetValue(null) is IDictionary dictionary) { if (dictionary[vecType.Cast(visualEffectCondition)] is Dictionary<string, GameObject[]> dictionary2 && dictionary2.Count > 0) { Get.Plugin.LogDebugOnly($"Patched visual effects lookup by skill, type = {shared.m_itemType}, key = {visualEffectCondition}, results = {num}"); __result = dictionary2; } } else { Get.Plugin.LogWarning("Failed to find Jewelcrafting.GemEffects.VisualEffects.effectPrefabsByType via reflection."); } } private static VisualEffectCondition SkillKey(SharedData shared) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_002a: 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_0033: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected I4, but got Unknown return (VisualEffectCondition)(shared.m_skillType | (((int)shared.m_skillType == 14 && shared.m_name.Contains("$item_crossbow_iron")) ? 4194318 : 0) | (((int)shared.m_skillType == 14 && shared.m_name.Contains("$item_crossbow_silver")) ? 5242894 : 0) | (((int)shared.m_skillType == 14 && shared.m_name.Contains("$item_crossbow_blackmetal")) ? 6291470 : 0)); } } public static class TooltipHelper { public static string Damage(float damage) { return string.Concat(new string[3] { "<color=orange>", Mathf.RoundToInt(damage).ToString(), "</color>" }); } public static string GetAoeTooltipForItem(ItemData item, Aoe aoe) { StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append(Environment.NewLine + Environment.NewLine + "$area_of_effect "); int num = Mathf.RoundToInt(aoe.m_hitInterval); if ((float)num * 2f < aoe.m_ttl) { if (num == 1) { stringBuilder.Append("($per_second) "); } else if (num >= 2) { stringBuilder.Append("($every " + num + " $seconds) "); } } if (aoe.m_damage.m_damage != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_damage: " + Damage(aoe.m_damage.m_damage)); } if (aoe.m_damage.m_blunt != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_blunt: " + Damage(aoe.m_damage.m_blunt)); } if (aoe.m_damage.m_slash != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_slash: " + Damage(aoe.m_damage.m_slash)); } if (aoe.m_damage.m_pierce != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_pierce: " + Damage(aoe.m_damage.m_pierce)); } if (aoe.m_damage.m_fire != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_fire: " + Damage(aoe.m_damage.m_fire)); } if (aoe.m_damage.m_frost != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_frost: " + Damage(aoe.m_damage.m_frost)); } if (aoe.m_damage.m_lightning != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_lightning: " + Damage(aoe.m_damage.m_lightning)); } if (aoe.m_damage.m_poison != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_poison: " + Damage(aoe.m_damage.m_poison)); } if (aoe.m_damage.m_spirit != 0f) { stringBuilder.Append(Environment.NewLine + "$inventory_spirit: " + Damage(aoe.m_damage.m_spirit)); } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] [HarmonyPriority(800)] public static class GetTooltipPatch { public static string Postfix(string __result, ItemData item) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Invalid comparison between Unknown and I4 //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 StringBuilder stringBuilder = new StringBuilder(256); stringBuilder.Append(__result); if (Object.op_Implicit((Object)(object)item.m_shared.m_attack.m_attackProjectile)) { Projectile component = item.m_shared.m_attack.m_attackProjectile.GetComponent<Projectile>(); if ((Object)(object)component != (Object)null && Object.op_Implicit((Object)(object)component.m_spawnOnHit)) { Aoe component2 = component.m_spawnOnHit.GetComponent<Aoe>(); if ((Object)(object)component2 != (Object)null && ((int)item.m_shared.m_itemType == 3 || (int)item.m_shared.m_itemType == 9)) { stringBuilder.Append(TooltipHelper.GetAoeTooltipForItem(item, component2)); } } } return stringBuilder.ToString(); } } [BepInPlugin("probablykory.MoreCrossbows", "MoreCrossbows", "1.2.11")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class MoreCrossbows : BaseUnityPlugin, IPlugin { public const string PluginAuthor = "probablykory"; public const string PluginName = "MoreCrossbows"; public const string PluginVersion = "1.2.11"; public const string PluginGUID = "probablykory.MoreCrossbows"; private static ConfigEntry<bool> isDebugEnabled = null; internal static MoreCrossbows Instance; internal AssetBundle assetBundle; internal Harmony harmony; internal BaseUnityPlugin jewelcrafting; private List<Feature> _features = new List<Feature>(); private static Dictionary<string, string> DefaultEnglishLanguageStrings = new Dictionary<string, string> { { "$area_of_effect", "Area effect" }, { "$every", "every" }, { "$seconds", "seconds" }, { "$per_second", "per second" }, { "$item_crossbow_wood", "Wooden crossbow" }, { "$item_crossbow_wood_description", "A crudely-made but powerful weapon." }, { "$item_crossbow_bronze", "Bronze crossbow" }, { "$item_crossbow_bronze_description", "A powerful weapon, forged in bronze." }, { "$item_crossbow_iron", "Iron crossbow" }, { "$item_crossbow_iron_description", "An accurate, powerful messenger of death." }, { "$item_crossbow_silver", "Silver crossbow" }, { "$item_crossbow_silver_description", "A sleek weapon, crafted from the mountain top." }, { "$item_crossbow_blackmetal", "Blackmetal crossbow" }, { "$item_crossbow_blackmetal_description", "A vicious thing. Handle with care." }, { "$item_bolt_wood", "Wood bolt" }, { "$item_bolt_wood_description", "A brittle crossbow bolt of sharpened wood." }, { "$item_bolt_fire", "Fire bolt" }, { "$item_bolt_fire_description", "A piercing bolt of fire." }, { "$item_bolt_silver", "Silver bolt" }, { "$item_bolt_silver_description", "A bolt to calm restless spirits." }, { "$item_bolt_poison", "Poison bolt" }, { "$item_bolt_poison_description", "A bitter dose for your enemies." }, { "$item_bolt_frost", "Frost bolt" }, { "$item_bolt_frost_description", "A piercing bolt of ice." }, { "$item_bolt_lightning", "Lightning bolt" }, { "$item_bolt_lightning_description", "Noone can know when or where it will strike." }, { "$item_arrow_lightning", "Lightning arrow" }, { "$item_arrow_lightning_description", "Noone can know when or where it will strike." }, { "$item_bolt_surtling", "Surtling bolt" }, { "$item_bolt_surtling_description", "Do not use indoors." }, { "$item_bolt_ooze", "Ooze bolt" }, { "$item_bolt_ooze_description", "The stench is unbearable..." }, { "$item_bolt_bile", "Bile bolt" }, { "$item_bolt_bile_description", "Handle with care." }, { "$item_bolt_ice", "Ice bolt" }, { "$item_bolt_ice_description", "Heart of the frozen mountain." }, { "$item_bolt_flametal", "Flametal bolt" }, { "$item_bolt_flametal_description", "Do not use indoors." } }; public ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("MoreCrossbows"); public bool Debug { get { if (isDebugEnabled == null) { return true; } return isDebugEnabled.Value; } } private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown harmony = new Harmony("probablykory.MoreCrossbows"); harmony.PatchAll(typeof(GetTooltipPatch)); assetBundle = AssetUtils.LoadAssetBundleFromResources("crossbows"); isDebugEnabled = this.Config("1 - General", "Debugging Enabled", value: false, "If on, mod will output alot more information in the debug log level."); Instance = this; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; CheckForJewelcrafting(); InitializeFeatures(); AddDefaultLocalizations(); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; LocalizationManager.OnLocalizationAdded += OnLocalizationAdded; ((BaseUnityPlugin)this).Config.ConfigReloaded += OnConfigReloaded; new ConfigWatcher(this); } private void CheckForJewelcrafting() { if (Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.jewelcrafting", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { jewelcrafting = value.Instance; this.LogInfo("Patching customized crossbow gem effects for Jewelcrafting."); JewelcraftingPatches.Initialize(harmony, jewelcrafting); } } private void OnConfigReloaded(object sender, EventArgs e) { this.LogDebugOnly("Config reloaded received."); AddOrRemoveFeatures(); } private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e) { this.LogDebugOnly("Configuration Sync received."); AddOrRemoveFeatures(); } private void OnVanillaPrefabsAvailable() { this.LogDebugOnly("Vanilla Prefabs Available received."); AddOrRemoveFeatures(); } private void OnDestroy() { this.LogDebugOnly("OnDestroy called."); SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; } private void RegisterCustomPrefab(AssetBundle bundle, string assetName) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown string text = assetName.Replace(".prefab", ""); if (!string.IsNullOrEmpty(text) && !PrefabManager.Instance.PrefabExists(text)) { CustomPrefab val = new CustomPrefab(bundle, assetName, true); this.LogDebugOnly("Registering " + ((Object)val.Prefab).name); if (val != null && val.IsValid()) { PrefabExtension.FixReferences(val.Prefab, true); PrefabManager.Instance.AddPrefab(val); } } } private void AddOrRemoveFeatures() { bool flag = true; int num = 0; int num2 = 0; int num3 = 0; foreach (Feature feature in _features) { bool flag2 = false; if (feature.EnabledConfigEntry == null) { flag2 = flag; } else { flag2 = feature.EnabledConfigEntry.Value; flag = flag && flag2; } this.LogDebugOnly("DEBUG: allFeaturesEnabled = " + flag); this.LogDebugOnly("DEBUG: Feature " + feature.Name + " is " + (flag2 ? "enabled" : "disabled") + " and " + (feature.LoadedInGame ? "Loaded" : "Unloaded")); if (flag2 != feature.LoadedInGame) { if (flag2) { if (feature.DependencyNames.Count > 0) { foreach (string dependencyName in feature.DependencyNames) { RegisterCustomPrefab(assetBundle, dependencyName); } } feature.Load(); num++; } else { feature.Unload(); num2++; } } else if (feature.LoadedInGame && feature.RequiresUpdate) { feature.Update(); num3++; } } string text = ""; if (num > 0) { text = string.Format("{0} feature{1} loaded", num, (num > 1) ? "s" : ""); text = ((num2 <= 0) ? (text + ".") : (text + " and ")); } if (num2 > 0) { text += string.Format("{0} feature{1} unloaded.", num2, (num2 > 1) ? "s" : ""); } if (num3 > 0) { if (text.Length > 0) { text += " "; } text += string.Format("{0} feature{1} updated.", num3, (num3 > 1) ? "s" : ""); } if (text.Length > 0) { this.LogInfo(text); } Entries.UpdateBrowsable(); } private void AddDefaultLocalizations() { this.LogDebugOnly("AddLocalizations called."); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, DefaultEnglishLanguageStrings); } private void OnLocalizationAdded() { this.LogDebugOnly("Localization Added received."); string location = ((object)Instance).GetType().Assembly.Location; char directorySeparatorChar = Path.DirectorySeparatorChar; string text = location.Replace(directorySeparatorChar + "MoreCrossbows.dll", ""); if (Paths.PluginPath.Equals(text)) { text = Utility.CombinePaths(new string[2] { Paths.PluginPath, "MoreCrossbows" }); } string text2 = Utility.CombinePaths(new string[4] { text, "Translations", "English", "english.json" }); string directoryName = Path.GetDirectoryName(text2); if (!Directory.Exists(directoryName) || !File.Exists(text2)) { Directory.CreateDirectory(directoryName); string contents = SimpleJson.SerializeObject((object)DefaultEnglishLanguageStrings); File.WriteAllText(text2, contents); this.LogDebugOnly("Default localizations written to " + text2); } LocalizationManager.OnLocalizationAdded -= OnLocalizationAdded; } private void InitializeFeatures() { _features.Add(new FeatureItem("CrossbowWood") { Category = "2 - Crossbows", Description = "Adds a new Wooden Crossbow weapon", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/CrossbowWood.prefab", Type = FeatureType.Crossbow, AmmoType = AmmunitionType.Bolt, Table = "Workbench", MinTableLevel = 2, Requirements = "Wood:20:5,Stone:8:2,LeatherScraps:8:2", Damages = "Pierce:27", Knockback = 80, DependencyNames = new List<string> { "sfx_wood_crossbow_fire.prefab" } }); _features.Add(new FeatureItem("CrossbowBronze") { Category = "2 - Crossbows", Description = "Adds a new Bronze Crossbow weapon", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/CrossbowBronze.prefab", Type = FeatureType.Crossbow, AmmoType = AmmunitionType.Bolt, Table = "Forge", MinTableLevel = 1, Requirements = "Wood:10:5,FineWood:4:2,Bronze:10:5,DeerHide:2:1", Damages = "Pierce:42", Knockback = 100, DependencyNames = new List<string> { "sfx_bronze_crossbow_fire.prefab" } }); _features.Add(new FeatureItem("CrossbowIron") { Category = "2 - Crossbows", Description = "Adds a new Iron Crossbow weapon", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/CrossbowIron.prefab", Type = FeatureType.Crossbow, AmmoType = AmmunitionType.Bolt, Table = "Forge", MinTableLevel = 2, Requirements = "Wood:10:5,ElderBark:4:2,Iron:20:10,Root:1", Damages = "Pierce:57", Knockback = 120 }); _features.Add(new FeatureItem("CrossbowSilver") { Category = "2 - Crossbows", Description = "Adds a new Silver Crossbow weapon", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/CrossbowSilver.prefab", Type = FeatureType.Crossbow, AmmoType = AmmunitionType.Bolt, Table = "Forge", MinTableLevel = 3, Requirements = "Wood:10:4,Silver:10:5,Iron:10:5,WolfHairBundle:6", Damages = "Pierce:72", Knockback = 140 }); _features.Add(new FeatureItem("CrossbowBlackmetal") { Category = "2 - Crossbows", Description = "Adds a new Blackmetal Crossbow weapon", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/CrossbowBlackmetal.prefab", Type = FeatureType.Crossbow, AmmoType = AmmunitionType.Bolt, Table = "Forge", MinTableLevel = 4, Requirements = "FineWood:10:5,BlackMetal:16:8,Iron:8:4,LoxPelt:2:1", Damages = "Pierce:92", Knockback = 160 }); _features.Add(new FeatureItem("BoltWood") { Category = "4 - Bolts", Description = "Adds new wood bolts", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/BoltWood.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "Workbench", MinTableLevel = 2, Requirements = "Wood:8", Damages = "Pierce:22", DependencyNames = new List<string> { "arbalest_projectile_wood.prefab" } }); _features.Add(new FeatureItem("BoltFire") { Category = "4 - Bolts", Description = "Adds new fire bolts", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/BoltFire.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "Workbench", MinTableLevel = 2, Requirements = "Wood:8,Resin:8,Feathers:2", Damages = "Pierce:11,Fire:22", DependencyNames = new List<string> { "arbalest_projectile_fire.prefab" } }); _features.Add(new FeatureItem("BoltSilver") { Category = "4 - Bolts", Description = "Adds new silver bolts", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/BoltSilver.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "Forge", MinTableLevel = 3, Requirements = "Wood:8,Silver:1,Feathers:2", Damages = "Pierce:52,Spirit:20", DependencyNames = new List<string> { "arbalest_projectile_wood.prefab" } }); _features.Add(new FeatureItem("BoltPoison") { Category = "4 - Bolts", Description = "Adds new poison bolts", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/BoltPoison.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "Workbench", MinTableLevel = 3, Requirements = "Wood:8,Obsidian:4,Feathers:2,Ooze:2", Damages = "Pierce:26,Poison:52", DependencyNames = new List<string> { "arbalest_projectile_poison.prefab" } }); _features.Add(new FeatureItem("BoltFrost") { Category = "4 - Bolts", Description = "Adds new frost bolts", EnabledByDefault = true, AssetPath = "Assets/PrefabInstance/BoltFrost.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "Workbench", MinTableLevel = 4, Requirements = "Wood:8,Obsidian:4,Feathers:2,FreezeGland:1", Damages = "Pierce:26,Frost:52", DependencyNames = new List<string> { "arbalest_projectile_frost.prefab" } }); _features.Add(new FeatureItem("BoltLightning") { Category = "4 - Bolts", Description = "Adds new lightning bolts", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltLightning.prefab", Type = FeatureType.Bolt, Amount = 20, Table = "BlackForge", MinTableLevel = 2, Requirements = "Wood:8,Feathers:2,Eitr:1", Damages = "Pierce:36,Lightning:62", DependencyNames = new List<string> { "sfx_lightning_hit.prefab", "arbalest_projectile_lightning.prefab" } }); _features.Add(new FeatureItem("ArrowLightning") { Category = "3 - Arrows", Description = "Adds new lightning arrows", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/ArrowLightning.prefab", Type = FeatureType.Arrow, Amount = 20, Table = "BlackForge", MinTableLevel = 2, Requirements = "Wood:8,Feathers:2,Eitr:1", Damages = "Pierce:36,Lightning:62", DependencyNames = new List<string> { "sfx_lightning_hit.prefab", "arbalest_projectile_lightning.prefab" } }); _features.Add(new FeatureItem("BoltOoze") { Category = "5 - Area Effect Bolts", Description = "Adds new Ooze bomb bolts. These cause the same Ooze explosions as bombs. Damage set here is applied to both projectile & explosion.", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltOoze.prefab", Type = FeatureType.Bolt, Amount = 10, Table = "Workbench", MinTableLevel = 1, Requirements = "Wood:4,Feathers:1,LeatherScraps:5,Ooze:5", Damages = "Pierce:5,Poison:40", AoePrefabName = "oozebomb_explosion", DependencyNames = new List<string> { "arbalest_projectile_ooze.prefab" } }); _features.Add(new FeatureItem("BoltSurtling") { Category = "5 - Area Effect Bolts", Description = "Adds new Surtling bolts. Damage set here is applied to both projectile & explosion.", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltSurtling.prefab", Type = FeatureType.Bolt, Amount = 10, Table = "Forge", MinTableLevel = 4, Requirements = "Wood:4,Feathers:1,SurtlingCore:3,Iron:1", Damages = "Pierce:22,Fire:18", AoePrefabName = "firebolt_explosion", DependencyNames = new List<string> { "arbalest_projectile_surtling.prefab", "firebolt_explosion.prefab" } }); _features.Add(new FeatureItem("BoltBile") { Category = "5 - Area Effect Bolts", Description = "Adds new Bile bomb bolts. These cause the same Bile explosions as bombs. Damage set here is applied to both projectile & explosion.", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltBile.prefab", Type = FeatureType.Bolt, Amount = 10, Table = "Workbench", MinTableLevel = 1, Requirements = "Wood:4,Feathers:1,Sap:3,Bilebag:3", Damages = "Pierce:22,Fire:15,Poison:30", AoePrefabName = "bilebomb_explosion", DependencyNames = new List<string> { "arbalest_projectile_bile.prefab" } }); _features.Add(new FeatureItem("BoltIce") { Category = "5 - Area Effect Bolts", Description = "Adds new Ice bolts which strike an area with frost damage. Damage set here is SPLIT between projectile & explosion.", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltIce.prefab", Type = FeatureType.Bolt, Amount = 10, Table = "Forge", MinTableLevel = 4, Requirements = "Wood:4,Feathers:1,FreezeGland:3,BlackMetal:1", Damages = "Pierce:22,Frost:62", AoePrefabName = "icebolt_explosion", DependencyNames = new List<string> { "arbalest_projectile_ice.prefab", "icebolt_explosion.prefab" } }); _features.Add(new FeatureItem("BoltFlametal") { Category = "5 - Area Effect Bolts", Description = "Adds new Flametal bolts. Hits all targets very hard. Damage set here is applied ONLY to projectile.", EnabledByDefault = false, AssetPath = "Assets/PrefabInstance/BoltFlametal.prefab", Type = FeatureType.Bolt, Amount = 10, Table = "BlackForge", MinTableLevel = 2, Requirements = "FlametalNew:1,Feathers:1,Eitr:3,SurtlingCore:3", Damages = "Blunt:22,Pierce:22,Fire:102", DependencyNames = new List<string> { "arbalest_projectile_flametal.prefab", "firebolt_explosion.prefab" } }); _features.Add(new FeatureRecipe("BoltBone") { Category = "4 - Bolts", Description = "Enables bone bolts to be craftable earlier", EnabledByDefault = true, Type = FeatureType.Bolt, Table = "Workbench", MinTableLevel = 2, Requirements = "BoneFragments:8,Feathers:2", Amount = 20 }); _features.Add(new FeatureRecipe("BoltIron") { Category = "4 - Bolts", Description = "Enables iron bolts to be craftable earlier", EnabledByDefault = true, Type = FeatureType.Bolt, Table = "Forge", MinTableLevel = 2, Requirements = "Wood:8,Iron:1,Feathers:2", Amount = 20 }); _features.Add(new FeatureRecipe("BoltBlackmetal") { Category = "4 - Bolts", Description = "Enables blackmetal bolts to be craftable earlier", EnabledByDefault = true, Type = FeatureType.Bolt, Table = "Forge", MinTableLevel = 4, Requirements = "Wood:8,BlackMetal:2,Feathers:2", Amount = 20 }); foreach (Feature feature in _features) { feature.Initialize(); } } ConfigFile IPlugin.get_Config() { return ((BaseUnityPlugin)this).Config; } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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; } } [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 Common { internal class AcceptableValueConfigNote : AcceptableValueBase { public virtual string Note { get; } public AcceptableValueConfigNote(string note) : base(typeof(string)) { if (string.IsNullOrEmpty(note)) { throw new ArgumentException("A string with atleast 1 character is needed", "Note"); } Note = note; } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return !string.IsNullOrEmpty(value as string); } public override string ToDescriptionString() { return "# Note: " + Note; } } internal static class ConfigHelper { public static ConfigurationManagerAttributes GetAdminOnlyFlag() { //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_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true }; } public static ConfigurationManagerAttributes GetTags(Action<ConfigEntryBase> action) { //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_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { CustomDrawer = action }; } public static ConfigurationManagerAttributes GetTags() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new ConfigurationManagerAttributes(); } public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, ConfigDescription description) { return instance.Config.Bind<T>(group, name, value, description); } public static ConfigEntry<T> Config<T>(this IPlugin instance, string group, string name, T value, string description) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return instance.Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { GetAdminOnlyFlag() })); } } internal static class RequirementsEntry { public static RequirementConfig[] Deserialize(string reqs) { return ((IEnumerable<string>)reqs.Split(new char[1] { ',' })).Select((Func<string, RequirementConfig>)delegate(string r) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown string[] array = r.Split(new char[1] { ':' }); int result; int result2; return new RequirementConfig { Item = array[0], Amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result), AmountPerLevel = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0), Recover = true }; }).ToArray(); } public static string Serialize(RequirementConfig[] reqs) { return string.Join(",", reqs.Select((RequirementConfig r) => (r.AmountPerLevel <= 0) ? $"{r.Item}:{r.Amount}" : $"{r.Item}:{r.Amount}:{r.AmountPerLevel}")); } } internal static class SharedDrawers { private static BaseUnityPlugin configManager; private static BaseUnityPlugin GetConfigManager() { if ((Object)(object)configManager == (Object)null && Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { configManager = value.Instance; } return configManager; } public static int GetRightColumnWidth() { int result = 130; BaseUnityPlugin val = GetConfigManager(); if ((Object)(object)val != (Object)null) { PropertyInfo propertyInfo = ((object)val)?.GetType().GetProperty("RightColumnWidth", BindingFlags.Instance | BindingFlags.NonPublic); if (propertyInfo != null) { result = (int)propertyInfo.GetValue(val); } } return result; } public static void ReloadConfigDisplay() { BaseUnityPlugin val = GetConfigManager(); if ((Object)(object)val != (Object)null) { object obj = ((object)val).GetType()?.GetProperty("DisplayingWindow")?.GetValue(val); if (obj is bool && (bool)obj) { ((object)val).GetType().GetMethod("BuildSettingList").Invoke(val, Array.Empty<object>()); } } } public static Action<ConfigEntryBase> DrawReqConfigTable(bool hasUpgrades = false) { return delegate(ConfigEntryBase cfg) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown List<RequirementConfig> list = new List<RequirementConfig>(); bool flag = false; int rightColumnWidth = GetRightColumnWidth(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); foreach (RequirementConfig item in RequirementsEntry.Deserialize((string)cfg.BoxedValue).ToList()) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = GUILayout.TextField(item.Item, new GUIStyle(GUI.skin.textField) { fixedWidth = rightColumnWidth - 33 - (hasUpgrades ? 37 : 0) - 21 - 21 - 12 }, Array.Empty<GUILayoutOption>()); string text2 = (string.IsNullOrEmpty(text) ? item.Item : text); flag = flag || text2 != item.Item; int num = item.Amount; if (int.TryParse(GUILayout.TextField(num.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 33f }, Array.Empty<GUILayoutOption>()), out var result) && result != num) { num = result; flag = true; } int num2 = item.AmountPerLevel; if (hasUpgrades && int.TryParse(GUILayout.TextField(num2.ToString(), new GUIStyle(GUI.skin.textField) { fixedWidth = 33f }, Array.Empty<GUILayoutOption>()), out var result2) && result2 != num2) { num2 = result2; flag = true; } if (GUILayout.Button("x", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; } else { list.Add(new RequirementConfig { Item = text2, Amount = num, AmountPerLevel = num2 }); } if (GUILayout.Button("+", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>())) { flag = true; list.Add(new RequirementConfig { Item = "<Prefab Name>", Amount = 1 }); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = RequirementsEntry.Serialize(list.ToArray()); } }; } } internal class ConfigWatcher { private BaseUnityPlugin configurationManager; private IPlugin plugin; public ConfigWatcher(IPlugin plugin) { if (plugin == null) { throw new ArgumentNullException("plugin"); } this.plugin = plugin; CheckForConfigManager(); } private void InitializeWatcher() { string fileName = Path.GetFileName(plugin.Config.ConfigFilePath); new Watcher(Path.GetDirectoryName(plugin.Config.ConfigFilePath), fileName).FileChanged += OnFileChanged; Get.Plugin.LogDebugOnly("File system watcher initialized."); } private void CheckForConfigManager() { PluginInfo value; if (GUIManager.IsHeadless()) { InitializeWatcher(); } else if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out value) && Object.op_Implicit((Object)(object)value.Instance)) { configurationManager = value.Instance; Get.Plugin.LogDebugOnly("Configuration manager found, hooking DisplayingWindowChanged"); EventInfo @event = ((object)configurationManager).GetType().GetEvent("DisplayingWindowChanged"); if (@event != null) { Action<object, object> action = OnConfigManagerDisplayingWindowChanged; Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method); @event.AddEventHandler(configurationManager, handler); } } else { InitializeWatcher(); } } private void OnFileChanged(object sender, FileSystemEventArgs e) { string configFilePath = plugin.Config.ConfigFilePath; if (!File.Exists(configFilePath)) { return; } try { plugin.Config.SaveOnConfigSet = false; plugin.Config.Reload(); plugin.Config.SaveOnConfigSet = true; } catch { Get.Plugin.LogError("There was an issue with your " + Path.GetFileName(configFilePath) + " file."); Get.Plugin.LogError("Please check the format and spelling."); } } private void OnConfigManagerDisplayingWindowChanged(object sender, object e) { if (!(bool)((object)configurationManager).GetType().GetProperty("DisplayingWindow").GetValue(configurationManager, null)) { plugin.Config.SaveOnConfigSet = false; plugin.Config.Reload(); plugin.Config.SaveOnConfigSet = true; } } } internal class CustomSyncedValueBase { private class Patches { [HarmonyPatch(typeof(ZNet), "Shutdown")] [HarmonyPostfix] private static void ZNet_Shutdown() { if (ZNetExtension.IsClientInstance(ZNet.instance)) { foreach (CustomSyncedValueBase syncedValue in SyncedValues) { syncedValue.OnResetFromServer(); } return; } foreach (CustomSyncedValueBase syncedValue2 in SyncedValues) { syncedValue2.OnServerShutdown(); } } } public readonly string Name; public readonly Type Type; private object? boxedValue; public object? LocalBaseValue; private CustomRPC customRPC; private static readonly HashSet<CustomSyncedValueBase> SyncedValues = new HashSet<CustomSyncedValueBase>(); private static Harmony harmony = null; public bool IsSourceOfTruth { get; private set; } = true; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(this, value); } } public event Action<object, object>? ValueChanged; protected CustomSyncedValueBase(string name, Type type, object? initialValue) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00af: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown Name = name; Type = type; SyncedValues.Add(this); if (harmony == null) { harmony = (Harmony)AccessTools.Field(typeof(Main), "Harmony").GetValue(null); harmony.PatchAll(typeof(Patches)); Get.Plugin.LogDebugOnly("Jotunn's harmony instance obtained, CustomSyncedValueBase+Patches applied."); } boxedValue = initialValue; customRPC = NetworkManager.Instance.AddRPC(Name + "_CustomSyncedValue_RPC", new CoroutineHandler(OnServerReceive), new CoroutineHandler(OnClientReceive)); SynchronizationManager.Instance.AddInitialSynchronization(customRPC, (Func<ZPackage>)GetPackage); } public void SendPackage() { if ((Object)(object)ZNet.instance == (Object)null) { Get.Plugin.LogDebugOnly("SendPackage called but am not connected."); } if (!SynchronizationManager.Instance.PlayerIsAdmin) { Get.Plugin.LogDebugOnly("SendPackage called but Player is not admin."); } if ((Object)(object)ZNet.instance != (Object)null && SynchronizationManager.Instance.PlayerIsAdmin) { ZPackage package = GetPackage(); if (ZNetExtension.IsClientInstance(ZNet.instance)) { customRPC.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), package); } else { customRPC.SendPackage(ZNet.instance.m_peers, package); } } } private ZPackage GetPackage() { return new PackageEntry { key = Name, type = Type, value = boxedValue }.ToPackage(); } private IEnumerator OnServerReceive(long sender, ZPackage package) { Get.Plugin.LogDebugOnly($"Server received RPC: {sender} {package}"); yield return null; ParsedEntries parsedEntries = package.ReadEntries(); if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value)) { BoxedValue = (LocalBaseValue = value.value); Get.Plugin.LogDebugOnly($"Set local and boxed: {value.value}"); customRPC.SendPackage(ZNet.instance.m_peers.Where((ZNetPeer x) => x.m_uid != sender).ToList(), package); } else { OnReceiveError(parsedEntries); } } private IEnumerator OnClientReceive(long sender, ZPackage package) { Get.Plugin.LogDebugOnly($"Client received RPC: {sender} {package}"); yield return null; ParsedEntries parsedEntries = package.ReadEntries(); if (parsedEntries.Count > 0 && parsedEntries.TryGetValue(Name, out var value)) { IsSourceOfTruth = false; if (LocalBaseValue == null) { LocalBaseValue = BoxedValue; } BoxedValue = value.value; Get.Plugin.LogDebugOnly($"Set source of truth: {IsSourceOfTruth}, {Environment.NewLine}local: {LocalBaseValue} {Environment.NewLine}boxed: {BoxedValue}"); } else { OnReceiveError(parsedEntries); } } private void OnReceiveError(ParsedEntries entries) { Get.Plugin.LogWarning(Name + "_CustomSyncedValue_RPC recieved package without expected key: " + Name); string text = ""; foreach (KeyValuePair<string, PackageEntry> entry in entries) { text += $"{entry.Key} - {entry.Value.type} - {entry.Value.value?.ToString()} {Environment.NewLine}"; } Get.Plugin.LogWarning("Result: " + Environment.NewLine + text); } private void OnResetFromServer() { BoxedValue = LocalBaseValue; IsSourceOfTruth = true; LocalBaseValue = null; } private void OnServerShutdown() { } } internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; if (base.BoxedValue != null) { SendPackage(); } } } public CustomSyncedValue(string name, T value = default(T)) : base(name, typeof(T), value) { } public void AssignLocalValue(T value) { if (base.IsSourceOfTruth && SynchronizationManager.Instance.PlayerIsAdmin) { Value = value; } else { LocalBaseValue = value; } } } internal class ParsedEntries : Dictionary<string, PackageEntry> { } internal class PackageEntry { public string key; public Type type; public object? value; } internal class InvalidDeserializationTypeException : Exception { public string expected; public string received; public string field = ""; } internal static class PackageUtils { public static string GetPackageTypeString(Type type) { return type.AssemblyQualifiedName; } public static void AddValue(this ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { package.AddValue(item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetPackageTypeString(fieldInfo.FieldType)); package.AddValue(fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } public static void AddEntry(this ZPackage package, PackageEntry entry) { package.Write(entry.key); package.Write((entry.value == null) ? "" : GetPackageTypeString(entry.type)); package.AddValue(entry.value); } public static ZPackage ToPackage(this PackageEntry packageEntry) { return new List<PackageEntry> { packageEntry }.ToPackage(); } public static ZPackage ToPackage(this IEnumerable<PackageEntry> packageEntries) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(packageEntries?.Count() ?? 0); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { val.AddEntry(item); } return val; } public static object ReadValueWithType(this ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, package.ReadValueWithType(fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = package.ReadValueWithType(type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { package.ReadValueWithType(type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.FirstOrDefault(); } public static ParsedEntries ReadEntries(this ZPackage package) { ParsedEntries parsedEntries = new ParsedEntries(); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string key = package.ReadString(); string text = package.ReadString(); Type type = Type.GetType(text); if (text == "" || type != null) { object obj; try { obj = ((text == "") ? null : package.ReadValueWithType(type)); } catch (InvalidDeserializationTypeException ex) { Get.Plugin.LogWarning("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text); continue; } if (obj != null) { parsedEntries[key] = new PackageEntry { key = key, type = type, value = obj }; } continue; } Get.Plugin.LogWarning("Got invalid type " + text + ", abort reading of received configs"); return new ParsedEntries(); } return parsedEntries; } public static void Test() { } } internal interface IPlugin { ConfigFile Config { get; } bool Debug { get; } ManualLogSource Logger { get; } } internal static class LoggingExtensions { private static readonly Dictionary<string, ManualLogSource> logSources = new Dictionary<string, ManualLogSource>(); internal static ManualLogSource GetLogger(this IPlugin mod) { if (mod.Debug) { Type declaringType = new StackFrame(2).GetMethod().DeclaringType; if (!logSources.TryGetValue(declaringType.FullName, out var value)) { value = Logger.CreateLogSource(declaringType.FullName); logSources.Add(declaringType.FullName, value); } return value; } return mod.Logger; } public static void LogDebugOnly(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogDebug(data); } } public static void LogDebug(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogDebug(data); } else { mod.Logger.LogDebug(data); } } public static void LogInfo(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogInfo(data); } else { mod.Logger.LogInfo(data); } } public static void LogMessage(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogMessage(data); } else { mod.Logger.LogMessage(data); } } public static void LogWarning(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogWarning(data); } else { mod.Logger.LogWarning(data); } } public static void LogError(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogError(data); } else { mod.Logger.LogError(data); } } public static void LogFatal(this IPlugin mod, object data) { if (mod.Debug) { mod.GetLogger().LogFatal(data); } else { mod.Logger.LogFatal(data); } } } internal static class Get { private static IPlugin cachedModRef; public static IPlugin Plugin { get { if (cachedModRef == null) { cachedModRef = AccessTools.Field((from p in new StackFrame(0).GetMethod().DeclaringType.Assembly.GetTypes() where typeof(IPlugin).IsAssignableFrom(p) select p).FirstOrDefault(), "Instance").GetValue(null) as IPlugin; cachedModRef.LogDebugOnly("Caching static mod reference"); } return cachedModRef; } } } internal class Watcher { private FileSystemWatcher fileSystemWatcher; public bool EnableRaisingEvents { get { if (fileSystemWatcher != null) { return fileSystemWatcher.EnableRaisingEvents; } return false; } set { if (fileSystemWatcher != null) { fileSystemWatcher.EnableRaisingEvents = value; } } } public event Action<object, FileSystemEventArgs>? FileChanged; public Watcher(string path, string filter) { if (path == null) { throw new ArgumentNullException("path"); } if (filter == null) { throw new ArgumentNullException("filter"); } Get.Plugin.LogDebugOnly("Watcher created for " + path + ", " + filter); fileSystemWatcher = new FileSystemWatcher(path, filter); fileSystemWatcher.Changed += OnCreatedChangedOrRenamed; fileSystemWatcher.Created += OnCreatedChangedOrRenamed; fileSystemWatcher.Renamed += OnCreatedChangedOrRenamed; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void OnCreatedChangedOrRenamed(object sender, FileSystemEventArgs args) { Get.Plugin.LogDebugOnly($"OnCreatedChangedOrRenamed triggered {args.Name}, {args.ChangeType}"); this.FileChanged?.Invoke(sender, args); } } }