Decompiled source of ShrineOfDisorder v1.1.7

ShrineOfDisorder.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using On.RoR2;
using R2API.Utils;
using RoR2;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShrineOfDisorder")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.5.0")]
[assembly: AssemblyInformationalVersion("1.1.5+c6bf74dff62d80f925ba9f9fcd1f6d7e5fa22526")]
[assembly: AssemblyProduct("ShrineOfDisorder")]
[assembly: AssemblyTitle("ShrineOfDisorder")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShrineOfDisorder
{
	public enum ShrineBehavior
	{
		RandomizeEachStack,
		RandomizeEachItem,
		SwapOneInventory,
		SwapAllInventories
	}
	public class ShrineConfig
	{
		public ConfigEntry<bool> lunarItemsCfg;

		public ConfigEntry<bool> bossItemsCfg;

		public ConfigEntry<bool> voidItemsCfg;

		public ConfigEntry<bool> voidBossItemsCfg;

		public ConfigEntry<ShrineBehavior> shrineBehaviorCfg;

		public ConfigEntry<bool> preserveStackCountCfg;

		public ConfigEntry<bool> onlyObtainedItemsCfg;

		public ConfigEntry<bool> shrineOnAllMapsCfg;

		public ConfigEntry<float> shrineSpawnMultiplierCfg;

		public bool lunarItems => lunarItemsCfg.Value;

		public bool bossItems => bossItemsCfg.Value;

		public bool voidItems => voidItemsCfg.Value;

		public bool voidBossItems => voidBossItemsCfg.Value;

		public ShrineBehavior shrineBehavior => shrineBehaviorCfg.Value;

		public bool preserveStackCount => preserveStackCountCfg.Value;

		public bool onlyObtainedItems => onlyObtainedItemsCfg.Value;

		public bool shrineOnAllMaps => shrineOnAllMapsCfg.Value;

		public float shrineSpawnMultiplier => shrineSpawnMultiplierCfg.Value;

		public ShrineConfig(ConfigFile cfg)
		{
			lunarItemsCfg = cfg.Bind<bool>("Items", "LunarItems", false, "Allow the shrine to randomize lunar items.");
			voidItemsCfg = cfg.Bind<bool>("Items", "VoidItems", false, "Allow the shrine to randomize void items.");
			bossItemsCfg = cfg.Bind<bool>("Items", "BossItems", false, "Allow the shrine to randomize boss items.");
			voidBossItemsCfg = cfg.Bind<bool>("Items", "VoidBossItems", false, "Allow the shrine to randomize void items.");
			shrineBehaviorCfg = cfg.Bind<ShrineBehavior>("Behavior", "ShrineBehavior", ShrineBehavior.RandomizeEachStack, "The behavior of the shrine. The inventory swapping behavior is only enabled for games with 2 or more players. Otherwise, the default behavior will be used.");
			preserveStackCountCfg = cfg.Bind<bool>("Behavior", "PreserveStackCount", true, "Preserve the number of unique stacks when using the RandomizeEachStack behavior. If disabled, the same item can be randomly selected for multiple stacks, effectively merging them.");
			onlyObtainedItemsCfg = cfg.Bind<bool>("Behavior", "OnlyObtainedItems", false, "When determining which items to give the player, only pick from the list of items that they already have in their inventory.");
			shrineOnAllMapsCfg = cfg.Bind<bool>("Behavior", "ShrineOnAllMaps", true, "Allow the shrine to spawn on all maps.");
			shrineSpawnMultiplierCfg = cfg.Bind<float>("Behavior", "ShrineSpawnMultiplier", 1f, "A multiplier on the shrine's spawn weight.");
		}
	}
	internal static class Log
	{
		internal static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			_logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void LogInfo(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void LogMessage(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	public static class DccsExtensions
	{
		public static int FindCategoryIndexByName_WorkingVersion(this DirectorCardCategorySelection dccs, string categoryName)
		{
			for (int i = 0; i < dccs.categories.Length; i++)
			{
				if (dccs.categories[i].name == categoryName)
				{
					return i;
				}
			}
			return -1;
		}

		public static DirectorCard GetCard(this DirectorCardCategorySelection dccs, int categoryIndex, string cardName)
		{
			DirectorCard[] cards = dccs.categories[categoryIndex].cards;
			foreach (DirectorCard val in cards)
			{
				if (((Object)val.spawnCard).name.StartsWith(cardName))
				{
					return val;
				}
			}
			return null;
		}

		public static bool HasCard(this DirectorCardCategorySelection dccs, int categoryIndex, string cardName)
		{
			return dccs.GetCard(categoryIndex, cardName) != null;
		}

		public static int GetWeight(this DirectorCardCategorySelection dccs, int categoryIndex, string cardName)
		{
			return dccs.GetCard(categoryIndex, cardName)?.selectionWeight ?? (-1);
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("cbrl.ShrineOfDisorder", "ShrineOfDisorder", "1.0.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class ShrineOfDisorder : BaseUnityPlugin
	{
		public const string PluginGUID = "cbrl.ShrineOfDisorder";

		public const string PluginAuthor = "cbrl";

		public const string PluginName = "ShrineOfDisorder";

		public const string PluginVersion = "1.0.0";

		public ShrineConfig config;

		private HashSet<ItemTier> enabledTiers = new HashSet<ItemTier>();

		private static Dictionary<ItemTier, List<ItemDef>> dropLists;

		private readonly string[] bannedStageNames = new string[4] { "bazaar", "artifactworld", "mysteryspace", "limbo" };

		private readonly string[] searchWeights = new string[3] { "iscShrineBoss", "iscShrineBlood", "iscShrineCombat" };

		private const int defaultShrineWeight = 3;

		public void Awake()
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			Log.Init(((BaseUnityPlugin)this).Logger);
			config = new ShrineConfig(((BaseUnityPlugin)this).Config);
			enabledTiers.Add((ItemTier)0);
			enabledTiers.Add((ItemTier)1);
			enabledTiers.Add((ItemTier)2);
			if (config.lunarItems)
			{
				enabledTiers.Add((ItemTier)3);
			}
			if (config.bossItems)
			{
				enabledTiers.Add((ItemTier)4);
			}
			if (config.voidBossItems)
			{
				enabledTiers.Add((ItemTier)9);
			}
			if (config.voidItems)
			{
				enabledTiers.Add((ItemTier)6);
				enabledTiers.Add((ItemTier)7);
				enabledTiers.Add((ItemTier)8);
			}
			Run.Start += new hook_Start(Run_Start);
			Inventory.ShrineRestackInventory += (hook_ShrineRestackInventory)delegate(orig_ShrineRestackInventory orig, Inventory self, Xoroshiro128Plus rng)
			{
				RestackBehavior(self, rng);
			};
			if (config.shrineOnAllMaps)
			{
				SceneDirector.onGenerateInteractableCardSelection += SceneDirector_onGenerateInteractableCardSelection;
			}
			Log.LogInfo("Awake done.");
		}

		private void SceneDirector_onGenerateInteractableCardSelection(SceneDirector director, DirectorCardCategorySelection selection)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!NetworkServer.active || bannedStageNames.Contains(((Object)Stage.instance).name))
				{
					return;
				}
				int index = selection.FindCategoryIndexByName_WorkingVersion("Shrines");
				if (index >= 0 && !selection.HasCard(index, "iscShrineRestack"))
				{
					int num = searchWeights.Select((string search) => selection.GetWeight(index, search)).FirstOrDefault((int weight) => weight != -1);
					if (num == 0)
					{
						num = 3;
					}
					DirectorCard val = new DirectorCard
					{
						spawnCard = Addressables.LoadAssetAsync<SpawnCard>((object)"RoR2/Base/ShrineRestack/iscShrineRestack.asset").WaitForCompletion(),
						selectionWeight = (int)((float)num * config.shrineSpawnMultiplier)
					};
					selection.AddCard(index, val);
					Log.LogInfo($"Added Shrine of Order card (iscShrineRestack) with weight: {val.selectionWeight}");
				}
				else if (index < 0)
				{
					Log.LogWarning("Could not find 'Shrines' category in stage " + ((Object)Stage.instance).name + ". The Shrine of Order will not be added to this stage.");
				}
				Category[] categories = selection.categories;
				foreach (Category val2 in categories)
				{
					Log.LogDebug($"Category: '{val2.name}'. Weight: {val2.selectionWeight}");
					foreach (DirectorCard item in val2.cards.Where((DirectorCard card) => card != null && (Object)(object)card.spawnCard != (Object)null))
					{
						Log.LogDebug($"  Card: {((Object)item.spawnCard).name} weight: {item.selectionWeight}");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError("Error in SceneDirector_onGenerateInteractableCardSelection: " + ex.Message);
				Log.LogError("Stack trace:\n" + ex.StackTrace);
			}
		}

		private void Run_Start(orig_Start orig, Run self)
		{
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			Dictionary<ItemTier, List<ItemDef>> dictionary = new Dictionary<ItemTier, List<ItemDef>>();
			dictionary.Add((ItemTier)0, Run.instance.availableTier1DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)1, Run.instance.availableTier2DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)2, Run.instance.availableTier3DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)3, Run.instance.availableLunarItemDropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)4, Run.instance.availableBossDropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)6, Run.instance.availableVoidTier1DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)7, Run.instance.availableVoidTier2DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)8, Run.instance.availableVoidTier3DropList.ConvertAll(GetItemDef));
			dictionary.Add((ItemTier)9, Run.instance.availableVoidBossDropList.ConvertAll(GetItemDef));
			dropLists = dictionary;
			foreach (KeyValuePair<ItemTier, List<ItemDef>> dropList in dropLists)
			{
				Log.LogDebug(string.Format("{0} Drop List: {1}", dropList.Key, string.Join(", ", dropList.Value)));
			}
		}

		private void Update()
		{
		}

		private void RestackBehavior(Inventory self, Xoroshiro128Plus rng)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			if (NetworkUser.readOnlyInstancesList.Count < 2)
			{
				ShrineBehavior shrineBehavior = config.shrineBehavior;
				ShrineBehavior shrineBehavior2 = shrineBehavior;
				if (shrineBehavior2 == ShrineBehavior.RandomizeEachItem)
				{
					RandomizeItems(self, rng);
				}
				else
				{
					RandomizeItemStacks(self, rng);
				}
				return;
			}
			switch (config.shrineBehavior)
			{
			case ShrineBehavior.RandomizeEachItem:
				RandomizeItems(self, rng);
				break;
			case ShrineBehavior.RandomizeEachStack:
				RandomizeItemStacks(self, rng);
				break;
			case ShrineBehavior.SwapOneInventory:
				SwapOneInventory(self, rng);
				break;
			case ShrineBehavior.SwapAllInventories:
				SwapAllInventories(rng);
				break;
			default:
				RandomizeItemStacks(self, rng);
				break;
			}
		}

		private static void ResetItems(Inventory inventory, List<ItemDef> items)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			foreach (ItemDef item in items)
			{
				inventory.ResetItemPermanent(item);
				inventory.itemAcquisitionOrder.Remove(item.itemIndex);
			}
		}

		private static Dictionary<ItemDef, int> GiveRandomItems(Inventory inventory, List<ItemDef> dropList, int count, Xoroshiro128Plus rng)
		{
			Dictionary<ItemDef, int> dictionary = new Dictionary<ItemDef, int>();
			for (int i = 0; i < count; i++)
			{
				ItemDef val = rng.NextElementUniform<ItemDef>(dropList);
				inventory.GiveItemPermanent(val, 1);
				if (!dictionary.ContainsKey(val))
				{
					dictionary[val] = 0;
				}
				dictionary[val]++;
			}
			return dictionary;
		}

		private static ItemDef GiveRandomStack(Inventory inventory, List<ItemDef> dropList, int count, Xoroshiro128Plus rng)
		{
			ItemDef val = rng.NextElementUniform<ItemDef>(dropList);
			inventory.GiveItemPermanent(val, count);
			return val;
		}

		private Dictionary<ItemTier, Dictionary<ItemDef, int>> GetItemCounts(Inventory inventory)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ItemTier, Dictionary<ItemDef, int>> dictionary = new Dictionary<ItemTier, Dictionary<ItemDef, int>>();
			foreach (ItemTier key in dropLists.Keys)
			{
				foreach (ItemDef item in dropLists[key])
				{
					int itemCountPermanent = inventory.GetItemCountPermanent(item.itemIndex);
					if (itemCountPermanent > 0)
					{
						if (!dictionary.ContainsKey(key))
						{
							dictionary.Add(key, new Dictionary<ItemDef, int>());
						}
						dictionary[key][item] = itemCountPermanent;
					}
				}
			}
			return dictionary;
		}

		private void RandomizeItems(Inventory self, Xoroshiro128Plus rng)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ItemTier, Dictionary<ItemDef, int>> itemCounts = GetItemCounts(self);
			foreach (ItemTier enabledTier in enabledTiers)
			{
				ResetItems(self, dropLists[enabledTier]);
			}
			((NetworkBehaviour)self).SetDirtyBit(8u);
			foreach (KeyValuePair<ItemTier, Dictionary<ItemDef, int>> item in itemCounts.Where((KeyValuePair<ItemTier, Dictionary<ItemDef, int>> pair) => enabledTiers.Contains(pair.Key)))
			{
				List<ItemDef> dropList = (config.onlyObtainedItems ? item.Value.Keys.ToList() : dropLists[item.Key]);
				int count = item.Value.Sum((KeyValuePair<ItemDef, int> pair) => pair.Value);
				GiveRandomItems(self, dropList, count, rng);
			}
		}

		private void RandomizeItemStacks(Inventory self, Xoroshiro128Plus rng)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ItemTier, Dictionary<ItemDef, int>> itemCounts = GetItemCounts(self);
			foreach (ItemTier enabledTier in enabledTiers)
			{
				ResetItems(self, dropLists[enabledTier]);
			}
			((NetworkBehaviour)self).SetDirtyBit(8u);
			foreach (KeyValuePair<ItemTier, Dictionary<ItemDef, int>> item2 in itemCounts.Where((KeyValuePair<ItemTier, Dictionary<ItemDef, int>> pair) => enabledTiers.Contains(pair.Key)))
			{
				ItemTier key = item2.Key;
				Dictionary<ItemDef, int> value = item2.Value;
				List<ItemDef> list = null;
				list = ((!config.preserveStackCount) ? (config.onlyObtainedItems ? value.Keys.ToList() : dropLists[key]) : new List<ItemDef>(config.onlyObtainedItems ? value.Keys.ToList() : dropLists[key]));
				foreach (KeyValuePair<ItemDef, int> item3 in value)
				{
					ItemDef item = GiveRandomStack(self, list, item3.Value, rng);
					if (config.preserveStackCount)
					{
						list.Remove(item);
					}
				}
			}
		}

		private void SwapOneInventory(Inventory self, Xoroshiro128Plus rng)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			List<Inventory> list = PlayerCharacterMasterController.instances.Select((PlayerCharacterMasterController user) => user.master.inventory).ToList();
			Inventory val = new Inventory();
			Inventory val2 = rng.NextElementUniform<Inventory>(list);
			val.CopyItemsFrom(self);
			self.CopyItemsFrom(val2);
			val2.CopyItemsFrom(val);
		}

		private void SwapAllInventories(Xoroshiro128Plus rng)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			List<Inventory> list = PlayerCharacterMasterController.instances.Select((PlayerCharacterMasterController user) => user.master.inventory).ToList();
			Inventory val = new Inventory();
			IOrderedEnumerable<Inventory> second = list.OrderBy((Inventory n) => rng.Next());
			foreach (var (val2, val3) in list.Zip(second, (Inventory a, Inventory b) => (a, b)))
			{
				val.CopyItemsFrom(val2);
				val2.CopyItemsFrom(val3);
				val3.CopyItemsFrom(val);
			}
		}

		private static ItemDef GetItemDef(PickupIndex index)
		{
			//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)
			return ItemCatalog.GetItemDef(PickupCatalog.GetPickupDef(index).itemIndex);
		}
	}
}