using 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);
}
}
}