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 ArcherArrowDrops v1.0.1
ArcherArrowDrops.dll
Decompiled 11 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ArcherArrowDrops")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("ArcherArrowDrops")] [assembly: AssemblyTitle("ArcherArrowDrops")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 ArcherArrowDrops { [BepInPlugin("com.dreich.archerarrowdrops", "ArcherArrowDrops", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ArcherArrowDropsPlugin : BaseUnityPlugin { public const string PluginGuid = "com.dreich.archerarrowdrops"; public const string PluginName = "ArcherArrowDrops"; public const string PluginVersion = "1.0.1"; internal const string ConfigSyncGuid = "_shudnal.ConditionalConfigSync"; private const long ReloadDelayTicks = 5000000L; private const long ReloadCooldownTicks = 20000000L; private static readonly (string enemyName, string defaultDrops)[] defaultEnemyDrops = new(string, string)[4] { ("Skeleton", "ArrowFlint,1,3,0.5"), ("Draugr_Ranged", "ArrowIron,1,3,0.5"), ("GoblinArcher", "ArrowNeedle,1,3,0.5"), ("Charred_Archer", "ArrowCharred,1,3,0.5") }; internal static readonly Dictionary<string, ConfigEntry<string>> dropSettingsByEnemy = new Dictionary<string, ConfigEntry<string>>(); internal static ConfigEntry<string> customEnemyDropsSetting; internal static ManualLogSource logger; internal static bool configSyncAvailable; private FileSystemWatcher configWatcher; private volatile bool reloadPending; private long lastChangeTicks; private long ignoreChangesUntilTicks; private void Awake() { //IL_0163: Unknown result type (might be due to invalid IL or missing references) logger = ((BaseUnityPlugin)this).Logger; configSyncAvailable = Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync"); if (configSyncAvailable) { ConfigSyncCompat.Initialize("com.dreich.archerarrowdrops", "ArcherArrowDrops", "1.0.1"); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"ConditionalConfigSync not found; configuration will not be synced from the server."); } ConfigEntry<bool> entry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "If on, the configuration is locked and can be changed by server admins only. Requires ConditionalConfigSync."); if (configSyncAvailable) { ConfigSyncCompat.AddLockingConfigEntry(entry); } (string, string)[] array = defaultEnemyDrops; for (int i = 0; i < array.Length; i++) { (string, string) tuple = array[i]; string item = tuple.Item1; string item2 = tuple.Item2; ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>(item, "Drops", item2, "Format: ItemPrefab,Min amount dropped,Max amount dropped, Chance to drop. Separate multiple drops with a semicolon, leave empty for no drops."); if (configSyncAvailable) { ConfigSyncCompat.AddServerControlledEntry(val); } dropSettingsByEnemy[item] = val; } customEnemyDropsSetting = ((BaseUnityPlugin)this).Config.Bind<string>("Custom Enemies", "Drops", "", "Add drops for any other enemy. Format: EnemyPrefab:ItemPrefab,Min amount dropped,Max amount dropped,Chance to drop. Separate multiple drops with a semicolon and multiple enemies with a vertical bar. Example: Fenring:ArrowWood,1,2,0.25|Troll:ArrowFlint,2,4,1.0"); if (configSyncAvailable) { ConfigSyncCompat.AddServerControlledEntry(customEnemyDropsSetting); } configWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)) { NotifyFilter = (NotifyFilters.Size | NotifyFilters.LastWrite) }; configWatcher.Changed += OnConfigFileChanged; configWatcher.EnableRaisingEvents = true; new Harmony("com.dreich.archerarrowdrops").PatchAll(); } private void OnConfigFileChanged(object sender, FileSystemEventArgs args) { long ticks = DateTime.UtcNow.Ticks; if (ticks >= Interlocked.Read(in ignoreChangesUntilTicks)) { Interlocked.Exchange(ref lastChangeTicks, ticks); reloadPending = true; } } private void Update() { if (!reloadPending || DateTime.UtcNow.Ticks - Interlocked.Read(in lastChangeTicks) <= 5000000) { return; } reloadPending = false; Interlocked.Exchange(ref ignoreChangesUntilTicks, DateTime.UtcNow.Ticks + 20000000); try { ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Config reload failed: " + ex.Message)); } } } internal static class ConfigSyncCompat { private static object configSync; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Initialize(string guid, string name, string version) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown configSync = (object)new ConfigSync(guid) { DisplayName = name, CurrentVersion = version, MinimumRequiredVersion = version, ModRequired = true }; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddLockingConfigEntry(ConfigEntry<bool> entry) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddLockingConfigEntry<bool>(entry); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddServerControlledEntry(ConfigEntry<string> entry) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddConfigEntry<string>(entry, (ConfigSyncMode)0); } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] internal static class AddArrowDropsPatch { private static readonly ConditionalWeakTable<CharacterDrop, List<Drop>> arrowDropsByEnemy = new ConditionalWeakTable<CharacterDrop, List<Drop>>(); private static void Prefix(CharacterDrop __instance) { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); List<Drop> orCreateValue = arrowDropsByEnemy.GetOrCreateValue(__instance); foreach (Drop item2 in orCreateValue) { __instance.m_drops.Remove(item2); } orCreateValue.Clear(); foreach (string dropEntry in GetDropEntries(prefabName)) { string[] array = dropEntry.Split(new char[1] { ',' }); if (array.Length != 4 || !int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { ArcherArrowDropsPlugin.logger.LogWarning((object)("Invalid drop for " + prefabName + ": " + dropEntry)); continue; } GameObject prefab = ZNetScene.instance.GetPrefab(array[0].Trim()); if ((Object)(object)prefab == (Object)null) { ArcherArrowDropsPlugin.logger.LogWarning((object)("Unknown item for " + prefabName + ": " + array[0])); continue; } Drop item = new Drop { m_prefab = prefab, m_amountMin = result, m_amountMax = Mathf.Max(result, result2), m_chance = Mathf.Clamp01(result3) }; __instance.m_drops.Add(item); orCreateValue.Add(item); } } private static IEnumerable<string> GetDropEntries(string enemyName) { string[] array; if (ArcherArrowDropsPlugin.dropSettingsByEnemy.TryGetValue(enemyName, out var value)) { array = value.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { yield return array[i]; } } array = ArcherArrowDropsPlugin.customEnemyDropsSetting.Value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { int num = text.IndexOf(':'); if (num >= 0 && !(text.Substring(0, num).Trim() != enemyName)) { string[] array2 = text.Substring(num + 1).Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < array2.Length; j++) { yield return array2[j]; } } } } } }