Decompiled source of ProductAppFix v1.0.1

ProductAppFix.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using HarmonyLib;
using MelonLoader;
using Microsoft.CodeAnalysis;
using ProductAppFix;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "ProductAppFix", "1.0.1", "HazDS", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ProductAppFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1f3fdc661951e620786a1435a8a4afacaf3558ce")]
[assembly: AssemblyProduct("ProductAppFix")]
[assembly: AssemblyTitle("ProductAppFix")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 ProductAppFix
{
	public class Core : MelonMod
	{
		private const float MAX_PRICE = 99999f;

		private static readonly Dictionary<string, float> _prices = new Dictionary<string, float>();

		private static readonly Dictionary<string, object> _productObjects = new Dictionary<string, object>();

		private static FieldInfo _productPricesField;

		[ThreadStatic]
		private static bool _settingPrice;

		[ThreadStatic]
		private static Dictionary<object, float> _savedOriginalPrices;

		public override void OnInitializeMelon()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0118: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_016c: Expected O, but got Unknown
			Type type = FindType("ScheduleOne.UI.Phone.ProductManagerApp.ProductAppDetailPanel");
			Type type2 = FindType("ScheduleOne.Product.ProductManager");
			if (type == null || type2 == null)
			{
				((MelonBase)this).LoggerInstance.Error("Failed to find required types.");
				return;
			}
			_productPricesField = type2.GetField("ProductPrices", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Core), "Awake_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = AccessTools.Method(type2, "GetPrice", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Core), "GetPrice_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo3 = AccessTools.Method(type2, "RpcLogic___SetPrice_4077118173", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(Core), "SetPriceRpc_Prefix", (Type[])null), new HarmonyMethod(typeof(Core), "SetPriceRpc_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo4 = AccessTools.Method(type2, "GetSaveString", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(Core), "GetSaveString_Prefix", (Type[])null), new HarmonyMethod(typeof(Core), "GetSaveString_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			((MelonBase)this).LoggerInstance.Msg("ProductAppFix loaded.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				_prices.Clear();
				_productObjects.Clear();
			}
		}

		private static void Awake_Postfix(object __instance)
		{
			object memberValue = GetMemberValue(__instance, "ValueLabel");
			if (memberValue != null)
			{
				PropertyInfo property = memberValue.GetType().GetProperty("characterLimit", BindingFlags.Instance | BindingFlags.Public);
				if (property != null)
				{
					property.SetValue(memberValue, 5);
				}
			}
		}

		private static bool GetPrice_Prefix(object __instance, object product, ref float __result)
		{
			if (product == null)
			{
				__result = 1f;
				return false;
			}
			string productId = GetProductId(product);
			if (productId != null)
			{
				_productObjects[productId] = product;
				if (_prices.TryGetValue(productId, out var value))
				{
					__result = value;
					return false;
				}
			}
			return true;
		}

		private static bool SetPriceRpc_Prefix(object __instance, string productID, float value)
		{
			if (_settingPrice)
			{
				return true;
			}
			float value2 = Mathf.RoundToInt(Mathf.Clamp(value, 1f, 99999f));
			_prices[productID] = value2;
			return true;
		}

		private static void SetPriceRpc_Postfix(object __instance, string productID, float value)
		{
			if (_settingPrice || _productPricesField == null || !_productObjects.TryGetValue(productID, out var value2) || !_prices.TryGetValue(productID, out var value3))
			{
				return;
			}
			object value4 = _productPricesField.GetValue(__instance);
			if (value4 == null)
			{
				return;
			}
			_settingPrice = true;
			try
			{
				DictSet(value4, value2, value3);
			}
			catch
			{
			}
			finally
			{
				_settingPrice = false;
			}
		}

		private static void GetSaveString_Prefix(object __instance)
		{
			if (_productPricesField == null || _prices.Count == 0)
			{
				return;
			}
			try
			{
				object value = _productPricesField.GetValue(__instance);
				if (value == null)
				{
					return;
				}
				_savedOriginalPrices = new Dictionary<object, float>();
				foreach (KeyValuePair<string, float> price in _prices)
				{
					if (_productObjects.TryGetValue(price.Key, out var value2))
					{
						try
						{
							float value3 = DictGet(value, value2);
							_savedOriginalPrices[value2] = value3;
							DictSet(value, value2, price.Value);
						}
						catch (Exception ex)
						{
							Melon<Core>.Logger.Warning("Dict access failed for " + price.Key + ": " + ex.Message);
						}
					}
				}
			}
			catch (Exception ex2)
			{
				Melon<Core>.Logger.Error("GetSaveString_Prefix failed: " + ex2.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex2.StackTrace);
			}
		}

		private static void GetSaveString_Postfix(object __instance, ref string __result)
		{
			try
			{
				if (_savedOriginalPrices != null && _savedOriginalPrices.Count > 0 && _productPricesField != null)
				{
					object value = _productPricesField.GetValue(__instance);
					if (value != null)
					{
						foreach (KeyValuePair<object, float> savedOriginalPrice in _savedOriginalPrices)
						{
							try
							{
								DictSet(value, savedOriginalPrice.Key, savedOriginalPrice.Value);
							}
							catch
							{
							}
						}
					}
				}
				if (__result == null || _prices.Count <= 0)
				{
					return;
				}
				foreach (KeyValuePair<string, float> price in _prices)
				{
					string text = Regex.Escape(price.Key);
					string text2 = ((int)price.Value).ToString();
					string pattern = "(\"String\"\\s*:\\s*\"" + text + "\"[^}]*?\"Int\"\\s*:\\s*)(\\d+)";
					string text3 = Regex.Replace(__result, pattern, "${1}" + text2);
					if (text3 != __result)
					{
						__result = text3;
					}
				}
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("GetSaveString_Postfix failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
			finally
			{
				_savedOriginalPrices = null;
			}
		}

		private static float DictGet(object dict, object key)
		{
			if (dict is IDictionary dictionary)
			{
				return Convert.ToSingle(dictionary[key]);
			}
			Type type = dict.GetType();
			MethodInfo? obj = type.GetMethod("get_Item", new Type[1] { key.GetType() }) ?? type.GetMethod("get_Item");
			if (obj == null)
			{
				Melon<Core>.Logger.Warning("get_Item not found on " + type.FullName);
				throw new MissingMethodException("get_Item");
			}
			return Convert.ToSingle(obj.Invoke(dict, new object[1] { key }));
		}

		private static void DictSet(object dict, object key, float value)
		{
			if (dict is IDictionary dictionary)
			{
				dictionary[key] = value;
				return;
			}
			Type type = dict.GetType();
			MethodInfo? obj = type.GetMethod("set_Item", new Type[2]
			{
				key.GetType(),
				typeof(float)
			}) ?? type.GetMethod("set_Item");
			if (obj == null)
			{
				Melon<Core>.Logger.Warning("set_Item not found on " + type.FullName);
				throw new MissingMethodException("set_Item");
			}
			obj.Invoke(dict, new object[2] { key, value });
		}

		private static object GetMemberValue(object obj, string name)
		{
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(obj);
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(obj);
			}
			return null;
		}

		private static string GetProductId(object product)
		{
			return GetMemberValue(product, "ID") as string;
		}

		private static Type FindType(string fullName)
		{
			string name = (fullName.StartsWith("ScheduleOne") ? ("Il2Cpp" + fullName) : fullName);
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(fullName) ?? assembly.GetType(name);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
}