Decompiled source of ShopUtils v1.0.8

ShopUtils.dll

Decompiled 7 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Boombox.ItemUtils;
using HarmonyLib;
using ShopUtils;
using ShopUtils.Language;
using ShopUtils.Network;
using Steamworks;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShopUtils")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ShopUtils")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1f772b7c-6b54-49f8-ba67-0c7e9aa1e152")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Boombox.ItemUtils
{
	[HarmonyPatch(typeof(ItemInstanceData))]
	internal static class ItemInstanceDataPatch
	{
		internal static int EntryCount;

		[HarmonyPrefix]
		[HarmonyPatch("GetEntryIdentifier")]
		private static bool GetEntryIdentifier(ref byte __result, Type type)
		{
			if (!Entries.registerEntries.Contains(type))
			{
				return true;
			}
			int num = EntryCount;
			foreach (Type registerEntry in Entries.registerEntries)
			{
				if (num == 255)
				{
					throw new ShopUtilsException("Item Instance Data Out of range > 255");
				}
				num++;
				if (registerEntry == type)
				{
					__result = (byte)num;
					return false;
				}
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetEntryType")]
		private static bool GetEntryType(ref ItemDataEntry __result, byte identifier)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			int num = EntryCount;
			foreach (Type registerEntry in Entries.registerEntries)
			{
				num++;
				if (identifier == (byte)num)
				{
					__result = (ItemDataEntry)registerEntry.GetConstructor(new Type[0]).Invoke(null);
					return false;
				}
			}
			return true;
		}
	}
}
namespace ShopUtils
{
	public static class Entries
	{
		internal static List<Type> registerEntries = new List<Type>();

		public static void RegisterEntry(Type type)
		{
			if (!type.IsSubclassOf(typeof(ItemDataEntry)))
			{
				throw new Exception("Unknown Item Data Entry: " + type.Name);
			}
			if (!registerEntries.Contains(type))
			{
				registerEntries.Add(type);
			}
		}

		public static void UnRegisterEntry(Type type)
		{
			if (registerEntries.Contains(type))
			{
				registerEntries.Remove(type);
			}
		}

		private static Type[] GetTypesFromAssembly(Assembly assembly)
		{
			try
			{
				return assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				UtilsLogger.LogWarning($"ItemDataEntry Register: {assembly} => {ex}");
				return ex.Types.Where((Type type) => type != null).ToArray();
			}
		}

		public static void RegisterAll(Assembly assembly)
		{
			Type[] typesFromAssembly = GetTypesFromAssembly(assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (type.IsSubclassOf(typeof(ItemDataEntry)) && !registerEntries.Contains(type))
				{
					registerEntries.Add(type);
					UtilsLogger.LogInfo($"Found ItemDataEntry: {type.Name}, Id: {registerEntries.Count + ItemInstanceDataPatch.EntryCount}");
				}
			}
		}

		public static void RegisterAll()
		{
			RegisterAll(Assembly.GetCallingAssembly());
		}

		internal static void InitEntryCount()
		{
			ItemInstanceDataPatch.EntryCount = -1;
			Type[] typesFromAssembly = GetTypesFromAssembly(Assembly.GetAssembly(typeof(ItemDataEntry)));
			Type[] array = typesFromAssembly;
			foreach (Type type in array)
			{
				if (type.IsSubclassOf(typeof(ItemDataEntry)))
				{
					ItemInstanceDataPatch.EntryCount++;
				}
			}
		}
	}
	public static class Items
	{
		internal static List<Item> registerItems = new List<Item>();

		public static void RegisterShopItem(Item item, ShopItemCategory category = 0, int price = -1)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			if ((Object)(object)item == (Object)null)
			{
				throw new ShopUtilsException("Item is null");
			}
			if (price >= 0)
			{
				item.price = price;
			}
			if ((int)category != 0)
			{
				item.Category = category;
			}
			if ((int)item.Category == 0)
			{
				throw new ShopUtilsException("Error Category Invalid \nItems Name: " + item.displayName + " \n");
			}
			if (item.price < 0)
			{
				throw new ShopUtilsException("Error Item Price \nItems Name: " + item.displayName + " \n");
			}
			item.purchasable = true;
			RegisterItem(item);
		}

		public static void RegisterSpawnableItem(Item item, float Rarity = 1f, int BudgetCost = 1)
		{
			if ((Object)(object)item == (Object)null)
			{
				throw new ShopUtilsException("Item is null");
			}
			item.rarity = Rarity;
			item.budgetCost = BudgetCost;
			item.spawnable = true;
			RegisterItem(item);
		}

		public static void UnRegisterItem(Item item)
		{
			if (registerItems.Contains(item))
			{
				registerItems.Remove(item);
			}
		}

		internal static void RegisterItem(Item item)
		{
			if (!registerItems.Contains(item))
			{
				registerItems.Add(item);
			}
		}

		internal static void InitAllItems()
		{
			registerItems.ForEach(delegate(Item item)
			{
				item.id = 0;
			});
			foreach (Item registerItem in registerItems)
			{
				if (TryGetMaxItemID(out var itemId))
				{
					registerItem.id = itemId;
					UtilsLogger.LogInfo("[Item: " + registerItem.displayName + ", " + $"ItemId: {registerItem.id}, " + "Guid: " + registerItem.persistentID + "]");
					continue;
				}
				UtilsLogger.LogError("Max Item Id Out of range > 255");
				break;
			}
		}

		internal static bool TryGetMaxItemID(out byte itemId)
		{
			int num = 0;
			Item[] objects = ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects;
			foreach (Item val in objects)
			{
				num = Math.Max(val.id, num);
			}
			foreach (Item registerItem in registerItems)
			{
				num = Math.Max(registerItem.id, num);
			}
			if (num == 255)
			{
				itemId = 0;
				return false;
			}
			itemId = (byte)(num + 1);
			return true;
		}
	}
	public static class Languages
	{
		internal static Dictionary<Locale, Dictionary<string, string>> languages = new Dictionary<Locale, Dictionary<string, string>>();

		public static void AddLanguage(string key, string language, Locale locale)
		{
			if ((Object)(object)locale == (Object)null)
			{
				throw new ShopUtilsException("Locale is null, key: " + key);
			}
			if (!languages.ContainsKey(locale))
			{
				languages.Add(locale, new Dictionary<string, string>());
			}
			if (languages[locale].ContainsKey(key))
			{
				UtilsLogger.LogError("Language: " + locale.LocaleName + " Has Already Key: " + key);
			}
			else
			{
				languages[locale].Add(key, language);
			}
		}

		public static void AddLanguage(this Locale locale, string key, string language)
		{
			AddLanguage(key, language, locale);
		}

		public static void AddLanguage(this Locale locale, params LanguageInstance[] languages)
		{
			foreach (LanguageInstance languageInstance in languages)
			{
				locale.AddLanguage(languageInstance.key, languageInstance.language);
			}
		}

		public static Locale GetLanguage(LanguageEnum language)
		{
			foreach (Locale locale in LocalizationSettings.AvailableLocales.Locales)
			{
				string value = language.ToString().Replace("Chinese", "");
				if (locale.LocaleName.Contains(value))
				{
					return locale;
				}
			}
			return null;
		}

		public static bool TryGetLanguage(string key, out string language)
		{
			if (languages.TryGetValue(LocalizationSettings.SelectedLocale, out var value) && value.ContainsKey(key))
			{
				language = value[key];
				return true;
			}
			language = null;
			return false;
		}

		public static void DebugLanguage()
		{
			foreach (Locale locale in LocalizationSettings.AvailableLocales.Locales)
			{
				UtilsLogger.LogInfo("Language: " + locale.LocaleName);
			}
		}
	}
	public class LanguageInstance
	{
		public string key;

		public string language;

		public LanguageInstance(string key, string language)
		{
			this.key = key;
			this.language = language;
		}
	}
	public static class UtilsLogger
	{
		private static ManualLogSource logger;

		internal static void InitLogger(ManualLogSource souce)
		{
			logger = souce;
		}

		public static void LogInfo(string message)
		{
			logger.LogInfo((object)message);
		}

		public static void LogError(string message)
		{
			logger.LogError((object)message);
		}

		public static void LogWarning(string message)
		{
			logger.LogWarning((object)message);
		}
	}
	public class ShopUtilsException : Exception
	{
		public ShopUtilsException(string message)
			: base(message)
		{
		}
	}
	[BepInPlugin("hyydsz-ShopUtils", "ShopUtils", "1.0.8")]
	public class PluginInfo : BaseUnityPlugin
	{
		public const string ModGUID = "hyydsz-ShopUtils";

		public const string ModName = "ShopUtils";

		public const string ModVersion = "1.0.8";

		private Harmony harmony = new Harmony("hyydsz-ShopUtils");

		private void Awake()
		{
			UtilsLogger.InitLogger(((BaseUnityPlugin)this).Logger);
			Entries.InitEntryCount();
			Networks.InitNetwork();
			harmony.PatchAll();
		}
	}
}
namespace ShopUtils.Network
{
	public static class Networks
	{
		private static CSteamID steamID;

		private static bool LobbyCreated;

		private static bool inLobby;

		public static Action OnLobbyCreated;

		public static Action OnLobbyEnter;

		public static Action OnLobbyLeave;

		public static Action OnLobbyCreateFailure;

		internal static void InitNetwork()
		{
			Callback<LobbyCreated_t>.Create((DispatchDelegate<LobbyCreated_t>)m_LobbyCreated);
			Callback<LobbyEnter_t>.Create((DispatchDelegate<LobbyEnter_t>)m_LobbyEnter);
		}

		private static void m_LobbyCreated(LobbyCreated_t lobby)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			if ((int)lobby.m_eResult == 1)
			{
				steamID = new CSteamID(lobby.m_ulSteamIDLobby);
				LobbyCreated = true;
				UtilsLogger.LogInfo("LobbyCreated.");
				OnLobbyCreated?.Invoke();
			}
			else
			{
				OnLobbyCreateFailure?.Invoke();
			}
		}

		private static void m_LobbyEnter(LobbyEnter_t lobby)
		{
			//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)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			steamID = new CSteamID(lobby.m_ulSteamIDLobby);
			inLobby = true;
			UtilsLogger.LogInfo("LobbyEntered.");
			OnLobbyEnter?.Invoke();
		}

		internal static void m_LobbyLeave()
		{
			((CSteamID)(ref steamID)).Clear();
			LobbyCreated = false;
			inLobby = false;
			OnLobbyLeave?.Invoke();
		}

		public static void RegisterItemPrice(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				throw new ShopUtilsException("Item is null");
			}
			string itemName = "Item-" + item.persistentID;
			OnLobbyCreated = (Action)Delegate.Combine(OnLobbyCreated, (Action)delegate
			{
				SetLobbyData(itemName, item.price.ToString());
			});
			OnLobbyEnter = (Action)Delegate.Combine(OnLobbyEnter, (Action)delegate
			{
				try
				{
					item.price = int.Parse(GetLobbyData(itemName));
				}
				catch
				{
					UtilsLogger.LogError("Sync Item Price Error. Item: " + item.displayName);
				}
			});
		}

		public static void SetLobbyData(string key, object value)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!LobbyCreated)
			{
				UtilsLogger.LogError("Cannot set lobby data when not create lobby");
			}
			else if (!SteamMatchmaking.SetLobbyData(steamID, key, value.ToString()))
			{
				UtilsLogger.LogError("Set lobby key Failure. Key: " + key);
			}
		}

		public static string GetLobbyData(string key)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!inLobby)
			{
				UtilsLogger.LogError("Cannot get lobby data when not in lobby");
				return null;
			}
			return SteamMatchmaking.GetLobbyData(steamID, key);
		}

		public static void SetNetworkSync(Dictionary<string, object> input, Action<Dictionary<string, string>> Action)
		{
			OnLobbyCreated = (Action)Delegate.Combine(OnLobbyCreated, (Action)delegate
			{
				foreach (KeyValuePair<string, object> item in input)
				{
					SetLobbyData(item.Key, item.Value);
				}
			});
			OnLobbyEnter = (Action)Delegate.Combine(OnLobbyEnter, (Action)delegate
			{
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				foreach (KeyValuePair<string, object> item2 in input)
				{
					dictionary.Add(item2.Key, GetLobbyData(item2.Key));
				}
				Action(dictionary);
			});
		}
	}
	[HarmonyPatch(typeof(SteamLobbyHandler))]
	internal static class SteamLobbyHandlerPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("LeaveLobby")]
		private static void LeaveLobby()
		{
			Networks.m_LobbyLeave();
		}
	}
}
namespace ShopUtils.Language
{
	public enum LanguageEnum
	{
		ChineseSimplified,
		ChineseTraditional,
		English,
		French,
		German,
		Italian,
		Japanese,
		Portuguese,
		Russian,
		Spanish,
		Ukrainian,
		Korean,
		Swedish
	}
	[HarmonyPatch(typeof(Item))]
	internal static class LanguagePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("GetTootipData")]
		private static bool GetTootipData(Item __instance, ref IEnumerable<IHaveUIData> __result)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			if (Items.registerItems.Contains(__instance) && __instance.Tooltips.Count > 0)
			{
				string key = ((Object)__instance).name.Trim().Replace(" ", "") + "_ToolTips";
				if (Languages.TryGetLanguage(key, out var language))
				{
					string[] array = language.Split(new char[1] { ';' });
					__instance.Tooltips = new List<ItemKeyTooltip>();
					string[] array2 = array;
					foreach (string text in array2)
					{
						__instance.Tooltips.Add(new ItemKeyTooltip(text));
					}
				}
				__result = (IEnumerable<IHaveUIData>)__instance.Tooltips;
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetLocalizedDisplayName")]
		private static bool GetLocalizedDisplayName(Item __instance, ref string __result)
		{
			if (Items.registerItems.Contains(__instance))
			{
				string key = ((Object)__instance).name.Trim().Replace(" ", "");
				if (Languages.TryGetLanguage(key, out var language))
				{
					__result = language;
					return false;
				}
				__result = __instance.displayName;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ShopItem))]
	internal static class ShopItemPatches
	{
		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static IEnumerable<CodeInstruction> ShopItem(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			FieldInfo display = AccessTools.Field(typeof(Item), "displayName");
			MethodInfo methodInfo = AccessTools.Method(typeof(Item), "GetLocalizedDisplayName", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Debug), "LogError", new Type[1] { typeof(object) }, (Type[])null);
			return new CodeMatcher(instructions, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction code) => code.opcode == OpCodes.Ldfld && (FieldInfo)code.operand == display)).ThrowIfInvalid("Couldn't find displayName").SetInstructionAndAdvance(new CodeInstruction(OpCodes.Call, (object)methodInfo))
				.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction code) => code.opcode == OpCodes.Ldstr))
				.ThrowIfInvalid("Couldn't find LogError")
				.RemoveInstructions(5)
				.InstructionEnumeration();
		}
	}
}
namespace ShopUtils.ItemUtils
{
	[HarmonyPatch(typeof(GameHandler))]
	internal static class GameHandlerPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Initialize")]
		private static void Initialize()
		{
			Items.InitAllItems();
			ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance;
			((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects = CollectionExtensions.AddRangeToArray<Item>(((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects, Items.registerItems.Where((Item i) => i.id != 0).ToArray());
		}
	}
	[HarmonyPatch(typeof(RoundArtifactSpawner))]
	internal static class RoundArtifactSpawnerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("SpawnRound")]
		private static void SpawnRound(RoundArtifactSpawner __instance)
		{
			__instance.possibleSpawns = CollectionExtensions.AddRangeToArray<Item>(__instance.possibleSpawns, Items.registerItems.Where((Item i) => i.id != 0 && i.spawnable).ToArray());
		}
	}
}