Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of ShrineOfDisorder v1.1.5
ShrineOfDisorder.dll
Decompiled 5 months agousing 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.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ShrineOfDisorder")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.5.0")] [assembly: AssemblyInformationalVersion("1.1.5+6262c21f4e90eac30b9c107451b935ba9cef7043")] [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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown 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 card 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; for (int i = 0; i < categories.Length; i++) { Category cat = categories[i]; string arg = string.Join("\n ", cat.cards.Select((DirectorCard card) => $"{cat.name}.{((Object)card.spawnCard).name} weight: {card.selectionWeight}")); Log.LogDebug($"{cat.name} weight: {cat.selectionWeight}\n {arg}"); } } private void Run_Start(orig_Start orig, Run self) { //IL_01e7: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); dropLists = new Dictionary<ItemTier, List<ItemDef>> { { (ItemTier)0, Run.instance.availableTier1DropList.ConvertAll(GetItemDef) }, { (ItemTier)1, Run.instance.availableTier2DropList.ConvertAll(GetItemDef) }, { (ItemTier)2, Run.instance.availableTier3DropList.ConvertAll(GetItemDef) }, { (ItemTier)3, Run.instance.availableLunarItemDropList.ConvertAll(GetItemDef) }, { (ItemTier)4, Run.instance.availableBossDropList.ConvertAll(GetItemDef) }, { (ItemTier)6, Run.instance.availableVoidTier1DropList.ConvertAll(GetItemDef) }, { (ItemTier)7, Run.instance.availableVoidTier2DropList.ConvertAll(GetItemDef) }, { (ItemTier)8, Run.instance.availableVoidTier3DropList.ConvertAll(GetItemDef) }, { (ItemTier)9, Run.instance.availableVoidBossDropList.ConvertAll(GetItemDef) } }; 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) { if (config.shrineBehavior == 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_001f: Unknown result type (might be due to invalid IL or missing references) foreach (ItemDef item in items) { inventory.ResetItem(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.GiveItem(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.GiveItem(val, count); return val; } private Dictionary<ItemTier, Dictionary<ItemDef, int>> GetItemCounts(Inventory inventory) { //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_0025: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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 itemCount = inventory.GetItemCount(item.itemIndex); if (itemCount > 0) { if (!dictionary.ContainsKey(key)) { dictionary.Add(key, new Dictionary<ItemDef, int>()); } dictionary[key][item] = itemCount; } } } return dictionary; } private void RandomizeItems(Inventory self, Xoroshiro128Plus rng) { //IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0000: 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) return ItemCatalog.GetItemDef(PickupCatalog.GetPickupDef(index).itemIndex); } } }