Decompiled source of CustomEndlessOddsCompat v1.0.1

patchers/CustomEndlessOddsPatcher.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[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("CustomEndlessOddsPatcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+d2d0ce7359494b4389d1ef1ff58e09d73dcf8e22")]
[assembly: AssemblyProduct("CustomEndlessOddsPatcher")]
[assembly: AssemblyTitle("CustomEndlessOddsPatcher")]
[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 CustomEndlessOddsPatcher
{
	public static class Patcher
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("CustomEndlessOddsPatcher");

		public static IEnumerable<string> TargetDLLs => Array.Empty<string>();

		public static void Patch(AssemblyDefinition assembly)
		{
		}

		public static void Initialize()
		{
			try
			{
				ReconcilePlugins();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error during plugin reconciliation: {arg}");
			}
		}

		private static void ReconcilePlugins()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Expected O, but got Unknown
			//IL_0102: 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_0113: Expected O, but got Unknown
			//IL_00a3: 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)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			string pluginPath = Paths.PluginPath;
			if (!Directory.Exists(pluginPath))
			{
				return;
			}
			string[] directories = Directory.GetDirectories(pluginPath, "*CustomEndless*", SearchOption.AllDirectories);
			for (int i = 0; i < directories.Length; i++)
			{
				string text = Path.Combine(directories[i], "OddsAndEnds.dll");
				if (!File.Exists(text))
				{
					continue;
				}
				bool flag = false;
				try
				{
					AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text, new ReaderParameters
					{
						ReadWrite = false
					});
					try
					{
						TypeDefinition type = val.MainModule.GetType("Severon.OddsAndEnds.Plugin");
						if (type != null)
						{
							CustomAttribute val2 = ((IEnumerable<CustomAttribute>)type.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute a) => ((MemberReference)a.AttributeType).Name == "BepInPlugin"));
							if (val2 != null)
							{
								CustomAttributeArgument val3 = val2.ConstructorArguments[0];
								if ((string)((CustomAttributeArgument)(ref val3)).Value == "com.severon.oddsandends")
								{
									flag = true;
								}
							}
						}
					}
					finally
					{
						((IDisposable)val)?.Dispose();
					}
					if (!flag)
					{
						continue;
					}
					Log.LogInfo((object)("Reconciling Custom Endless BepInPlugin GUID in '" + text + "'..."));
					string text2 = text + ".tmp";
					AssemblyDefinition val4 = AssemblyDefinition.ReadAssembly(text, new ReaderParameters
					{
						ReadWrite = false
					});
					try
					{
						((AssemblyNameReference)val4.Name).Name = "OddsAndEnds";
						((ModuleReference)val4.MainModule).Name = "OddsAndEnds.dll";
						TypeDefinition type2 = val4.MainModule.GetType("Severon.OddsAndEnds.Plugin");
						CustomAttribute obj = ((IEnumerable<CustomAttribute>)type2.CustomAttributes).First((CustomAttribute a) => ((MemberReference)a.AttributeType).Name == "BepInPlugin");
						obj.ConstructorArguments[0] = new CustomAttributeArgument(val4.MainModule.TypeSystem.String, (object)"com.cesech.customendless");
						obj.ConstructorArguments[1] = new CustomAttributeArgument(val4.MainModule.TypeSystem.String, (object)"Custom Endless");
						obj.ConstructorArguments[2] = new CustomAttributeArgument(val4.MainModule.TypeSystem.String, (object)"1.0.23");
						MethodDefinition val5 = ((IEnumerable<MethodDefinition>)type2.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == "Awake"));
						if (val5 != null)
						{
							Enumerator<Instruction> enumerator = val5.Body.Instructions.GetEnumerator();
							try
							{
								while (enumerator.MoveNext())
								{
									Instruction current = enumerator.Current;
									if (current.OpCode == OpCodes.Ldstr && (string)current.Operand == "com.severon.oddsandends")
									{
										current.Operand = "com.cesech.customendless";
									}
								}
							}
							finally
							{
								((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
							}
						}
						val4.Write(text2);
					}
					finally
					{
						((IDisposable)val4)?.Dispose();
					}
					string text3 = text + ".original";
					if (File.Exists(text3))
					{
						File.Delete(text3);
					}
					File.Move(text, text3);
					File.Move(text2, text);
					Log.LogInfo((object)"[CustomEndless] Successfully updated GUID to 'com.cesech.customendless'.");
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Failed checking/patching CustomEndless: " + ex.Message));
				}
			}
			directories = Directory.GetDirectories(pluginPath, "*Odds*Ends*", SearchOption.AllDirectories);
			foreach (string text4 in directories)
			{
				if (text4.IndexOf("CustomEndless", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					continue;
				}
				string text5 = Path.Combine(text4, "OddsAndEnds.dll");
				string text6 = Path.Combine(text4, "OddsAndEndsTrue.dll");
				if (!File.Exists(text5))
				{
					continue;
				}
				Log.LogInfo((object)"Reconciling Odds and Ends assembly name to prevent Mono conflict with CustomEndless...");
				try
				{
					AssemblyDefinition val6 = AssemblyDefinition.ReadAssembly(text5, new ReaderParameters
					{
						ReadWrite = false
					});
					try
					{
						if (val6.MainModule.GetType("Severon.OddsAndEndsTrue.Plugin") != null)
						{
							((AssemblyNameReference)val6.Name).Name = "OddsAndEndsTrue";
							((ModuleReference)val6.MainModule).Name = "OddsAndEndsTrue.dll";
							val6.Write(text6);
						}
					}
					finally
					{
						((IDisposable)val6)?.Dispose();
					}
					string text7 = text5 + ".original";
					if (File.Exists(text7))
					{
						File.Delete(text7);
					}
					File.Move(text5, text7);
					Log.LogInfo((object)("Successfully renamed Odds and Ends to '" + text6 + "'."));
				}
				catch (Exception ex2)
				{
					Log.LogError((object)("Failed checking/patching Odds and Ends: " + ex2.Message));
				}
			}
		}
	}
}

plugins/CustomEndlessOddsCompat/CustomEndlessOddsCompat.dll

Decompiled 8 hours 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.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OddsAndEndsTrue;
using Severon.OddsAndEnds;
using UnityEngine;

[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("CustomEndlessOddsCompat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+d2d0ce7359494b4389d1ef1ff58e09d73dcf8e22")]
[assembly: AssemblyProduct("CustomEndlessOddsCompat")]
[assembly: AssemblyTitle("CustomEndlessOddsCompat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[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 CustomEndlessOddsCompat
{
	[BepInPlugin("com.craft.customendlessoddscompat", "Custom Endless & Odds And Ends Compatibility", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("com.craft.customendlessoddscompat").PatchAll();
			Log.LogInfo((object)"Custom Endless & Odds And Ends Compatibility v1.0.1 initialized successfully. Custom Endless & Odds And Ends are now synchronized!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.craft.customendlessoddscompat";

		public const string PLUGIN_NAME = "Custom Endless & Odds And Ends Compatibility";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace CustomEndlessOddsCompat.Patches
{
	[HarmonyPatch(typeof(EndlessSettings), "RegisterAllSettings")]
	public static class EndlessSettingsMenuPatch
	{
		[HarmonyPostfix]
		public static void Postfix(EndlessSettings __instance)
		{
			MenuSettingsManager value = Traverse.Create((object)__instance).Field("menuSettingsManager").GetValue<MenuSettingsManager>();
			if ((Object)(object)value == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[SettingsMenuPatch] MenuSettingsManager not found on EndlessSettings.");
				return;
			}
			string menuTag = __instance.menuTag;
			value.Register(menuTag, "Awakened Amalgamator", "item_amalgamator", (SettingType)0, "0", "STARTING ITEMS");
			value.Register(menuTag, "Pestle", "item_pestle", (SettingType)0, "0", "STARTING ITEMS");
			value.Register(menuTag, "Demalgamator", "item_demalgamator", (SettingType)0, "0", "STARTING ITEMS");
			value.Register(menuTag, "Stoner Rock", "item_stoner_rock", (SettingType)0, "0", "STARTING ITEMS");
			value.Register(menuTag, "Time Reagent", "item_reagent_time", (SettingType)0, "0", "REAGENTS");
			value.Register(menuTag, "Power Reagent", "item_reagent_power", (SettingType)0, "0", "REAGENTS");
			value.Register(menuTag, "Magic Reagent", "item_reagent_magic", (SettingType)0, "0", "REAGENTS");
			value.Register(menuTag, "Body Reagent", "item_reagent_body", (SettingType)0, "0", "REAGENTS");
			value.Register(menuTag, "Soul Reagent", "item_reagent_soul", (SettingType)0, "0", "REAGENTS");
			Plugin.Log.LogInfo((object)"[SettingsMenuPatch] Injected Odds and Ends items & reagents into Custom Endless menu.");
		}
	}
	[HarmonyPatch(typeof(EndlessConfiguration), "GiveStartingItems")]
	public static class EndlessStartingItemsPatch
	{
		private static readonly (string settingKey, string prefabName)[] ItemMappings = new(string, string)[9]
		{
			("item_amalgamator", "Awakened_Amalgamator"),
			("item_pestle", "Item_Amalgamate_Pestle"),
			("item_demalgamator", "Item_Demalgamator"),
			("item_stoner_rock", "Item_Stoner_Rock"),
			("item_reagent_time", "Item_Time_Reagent"),
			("item_reagent_power", "Item_Power_Reagent"),
			("item_reagent_magic", "Item_Magic_Reagent"),
			("item_reagent_body", "Item_Body_Reagent"),
			("item_reagent_soul", "Item_Soul_Reagent")
		};

		[HarmonyPostfix]
		public static void Postfix()
		{
			if ((Object)(object)Inventory.instance == (Object)null)
			{
				return;
			}
			bool flag = false;
			(string, string)[] itemMappings = ItemMappings;
			for (int i = 0; i < itemMappings.Length; i++)
			{
				(string, string) tuple = itemMappings[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				int countState = CustomUIManager.GetCountState(item, 0);
				if (countState > 0)
				{
					GiveItem(item2, countState);
					Plugin.Log.LogInfo((object)$"[StartingItemsPatch] Granted {countState}x {item2} to player.");
					if (item == "item_amalgamator" || item == "item_pestle")
					{
						flag = true;
					}
				}
			}
			if (flag)
			{
				EnsureStudentNote();
			}
		}

		private static void GiveItem(string prefabName, int count)
		{
			for (int i = 0; i < count; i++)
			{
				Item_Object itemObjectPrefab = CL_AssetManager.GetItemObjectPrefab(prefabName, "");
				if ((Object)(object)itemObjectPrefab != (Object)null && itemObjectPrefab.itemData != null)
				{
					Item clone = itemObjectPrefab.itemData.GetClone((Item)null, false);
					Inventory.instance.AddItemToInventoryCenter(clone);
				}
				else
				{
					Plugin.Log.LogWarning((object)("[StartingItemsPatch] Could not find prefab for '" + prefabName + "'."));
				}
			}
		}

		private static void EnsureStudentNote()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			if ((Object)(object)Inventory.instance == (Object)null || Inventory.instance.bagItems == null)
			{
				return;
			}
			foreach (Item bagItem in Inventory.instance.bagItems)
			{
				if (bagItem != null && bagItem.data != null && bagItem.data.Contains("AwakenedStudentNote=1"))
				{
					return;
				}
			}
			Item_Object itemObjectPrefab = CL_AssetManager.GetItemObjectPrefab("Item_Note_01", "");
			if ((Object)(object)itemObjectPrefab != (Object)null && itemObjectPrefab.itemData != null)
			{
				Item clone = itemObjectPrefab.itemData.GetClone((Item)null, false);
				clone.dataModules = new List<Item_Data> { (Item_Data)new Item_Data_Text_Random
				{
					strings = new List<string> { "\r\nReagents:\r\nTime\r\nPower\r\nMagic\r\nBody\r\n\r\nSoul?\r\n        ", "\r\nThe Pestle can do more than \r\ndeconstruct items into Reagents\r\n        " }
				} };
				if (clone.data == null)
				{
					clone.data = new List<string>();
				}
				clone.data.Add("AwakenedStudentNote=1");
				Inventory.instance.AddItemToInventoryCenter(clone);
			}
		}
	}
	[HarmonyPatch(typeof(CL_Initializer), "Awake")]
	public static class GamemodeIntegrationPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)EndlessConfiguration.EndlessMode == (Object)null))
			{
				M_Gamemode endlessMode = EndlessConfiguration.EndlessMode;
				if (endlessMode.gamemodeSettings != null)
				{
					endlessMode.gamemodeSettings = new List<GamemodeSetting>(endlessMode.gamemodeSettings);
				}
				else
				{
					endlessMode.gamemodeSettings = new List<GamemodeSetting>();
				}
				if (!endlessMode.gamemodeSettings.Exists((GamemodeSetting s) => (Object)(object)s != (Object)null && s.id == "EnemyWaves"))
				{
					GamemodeSetting val = ScriptableObject.CreateInstance<GamemodeSetting>();
					val.id = "EnemyWaves";
					val.title = "Enemy Waves";
					val.description = "Spawn enemy waves as you climb.";
					val.color = Color.red;
					val.exclusiveSettings = new List<string>();
					val.unlock = ScriptableObject.CreateInstance<ProgressionUnlock>();
					val.unlock.unlockRequirements = new List<UnlockRequirement>();
					val.unlock.state = true;
					endlessMode.gamemodeSettings.Add(val);
					Plugin.Log.LogInfo((object)"[GamemodeIntegration] Injected EnemyWaves setting into Custom Endless.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(EndlessSettings), "get_startingPerkTitles")]
	public static class PerkRegistrationSafeguardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(ref Dictionary<string, string> __result)
		{
			try
			{
				StudentPerks.EnsureRegistered();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[PerkSafeguard] Error ensuring StudentPerks registered: " + ex.Message));
			}
			List<Perk> source = CL_AssetManager.GetFullCombinedAssetDatabase()?.perkAssets ?? new List<Perk>();
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			foreach (Perk item in from p in source
				where (Object)(object)p != (Object)null && !string.IsNullOrEmpty(p.id)
				orderby p.title
				select p)
			{
				if (!dictionary.ContainsKey(item.id))
				{
					dictionary.Add(item.id, item.title ?? item.id);
				}
			}
			__result = dictionary;
			return false;
		}
	}
}