Decompiled source of BetterMarketPlus v1.2.2
BepInEx/plugins/BetterMarketPlus.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BetterMarketPlus.Compatibility; using BetterMarketPlus.Configuration; using BetterMarketPlus.Localization; using HarmonyLib; using Newtonsoft.Json; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BetterMarketPlus")] [assembly: AssemblyDescription("Better Market Plus mod for Old Market Simulator by Ice Box Studio")] [assembly: AssemblyCompany("Ice Box Studio")] [assembly: AssemblyProduct("BetterMarketPlus")] [assembly: AssemblyCopyright("Copyright © 2025 Ice Box Studio All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("EAAD3296-E8E3-4C52-BF86-6907CB4F80E6")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.2.2.0")] namespace BetterMarketPlus { [BepInPlugin("IceBoxStudio.BetterMarketPlus", "BetterMarketPlus", "1.2.2")] [BepInIncompatibility("ViViKo.BetterMarket")] public class BetterMarketPlus : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("IceBoxStudio.BetterMarketPlus"); public static BetterMarketPlus Instance; private bool patchesApplied; internal static ManualLogSource Logger { get; private set; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; try { _ = LocalizationManager.Instance; Logger.LogInfo((object)"============================================="); Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.initializing")); Logger.LogInfo((object)(LocalizationManager.Instance.GetLocalizedText("plugin.author_prefix") + "Ice Box Studio(https://steamcommunity.com/id/ibox666/)")); Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.runtime", Environment.Version)); Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.unity_version", Application.unityVersion)); Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.harmony_version", HarmonyVersion())); Logger.LogInfo((object)"============================================="); ConfigManager.Initialize(((BaseUnityPlugin)this).Config); ApplyPatches(); Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.initialized")); } catch (Exception ex) { Logger.LogError((object)("BetterMarketPlus 初始化错误: " + ex.Message + "\n" + ex.StackTrace)); } } private string HarmonyVersion() { try { return typeof(Harmony).Assembly.GetName().Version.ToString(); } catch { return LocalizationManager.Instance.GetLocalizedText("plugin.unknown"); } } private void ApplyPatches() { if (!patchesApplied) { try { Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.applying_patches")); harmony.PatchAll(); patchesApplied = true; Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.patches_applied")); return; } catch (Exception ex) { Logger.LogError((object)("应用 BetterMarketPlus 时出错: " + ex.Message + "\n" + ex.StackTrace)); return; } } Logger.LogInfo((object)LocalizationManager.Instance.GetLocalizedText("plugin.patches_skipped")); } } public static class PluginInfo { public const string PLUGIN_GUID = "IceBoxStudio.BetterMarketPlus"; public const string PLUGIN_NAME = "BetterMarketPlus"; public const string PLUGIN_VERSION = "1.2.2"; } } namespace BetterMarketPlus.Patches { [HarmonyPatch(typeof(BlockAlcoholMachine))] public class BlockAlcoholMachinePatch { private static readonly FieldInfo currentOutputField = AccessTools.Field(typeof(BlockAlcoholMachine), "currentOutput"); private static readonly FieldInfo remainingDaysField = AccessTools.Field(typeof(BlockAlcoholMachine), "remainingDays"); private static long GetCurrentOutput(BlockAlcoholMachine instance) { object value = currentOutputField.GetValue(instance); return (long)value.GetType().GetProperty("Value").GetValue(value); } private static int GetRemainingDays(BlockAlcoholMachine instance) { object value = remainingDaysField.GetValue(instance); return (int)value.GetType().GetProperty("Value").GetValue(value); } [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void Postfix(BlockAlcoholMachine __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("BlockAlcoholMachine")) { return; } long currentOutput = GetCurrentOutput(__instance); int remainingDays = GetRemainingDays(__instance); if (currentOutput != -1) { ItemSO itemById = GameManager.Instance.GetItemById(currentOutput); __result = itemById.GetLocalizedName(); if (remainingDays > 0) { string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", remainingDays); __result = __result + " <i><color=yellow>[" + localizedDaysWithPrefix + "]</color></i>"; } } } } [HarmonyPatch(typeof(BlockAnimal))] public class BlockAnimalPatch { private static readonly FieldInfo animalSOField = AccessTools.Field(typeof(BlockAnimal), "animalSO"); [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void Postfix(BlockAnimal __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockAnimal")) { object? value = animalSOField.GetValue(__instance); AnimalSO val = (AnimalSO)((value is AnimalSO) ? value : null); if (__instance.dayCounter.Value < val.daysToHarvestAfterGrowth) { int days = val.daysToHarvestAfterGrowth - __instance.dayCounter.Value; string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", days); __result = __result + " <i><color=yellow>[" + localizedDaysWithPrefix + "]</color></i>"; } } } } [HarmonyPatch(typeof(BlockBeeHive))] public class BlockBeeHivePatch { private static readonly FieldInfo dayCounterField = AccessTools.Field(typeof(BlockBeeHive), "dayCounter"); private static readonly FieldInfo hasBeeField = AccessTools.Field(typeof(BlockBeeHive), "hasBee"); private static readonly FieldInfo blockBlueprintField = AccessTools.Field(typeof(PlayerInventory), "blockBlueprint"); private static Dictionary<int, RadiusVisualizer> visualizers = new Dictionary<int, RadiusVisualizer>(); private static HashSet<int> targetedThisFrame = new HashSet<int>(); private static HashSet<int> targetedLastFrame = new HashSet<int>(); private static int lastUpdateFrame; private static Dictionary<GameObject, RadiusVisualizer> ghostVisualizers = new Dictionary<GameObject, RadiusVisualizer>(); private static int GetDayCounter(BlockBeeHive instance) { object value = dayCounterField.GetValue(instance); return (int)value.GetType().GetProperty("Value").GetValue(value); } private static bool GetHasBee(BlockBeeHive instance) { object value = hasBeeField.GetValue(instance); return (bool)value.GetType().GetProperty("Value").GetValue(value); } private static GameObject GetBlockBlueprint(PlayerInventory instance) { object? value = blockBlueprintField.GetValue(instance); return (GameObject)((value is GameObject) ? value : null); } private static int CountTreesAround(BlockBeeHive instance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) int num = 0; Collider[] array = Physics.OverlapSphere(((Component)instance).transform.position, (float)instance.treeDetectionRadius); foreach (Collider val in array) { if (!val.isTrigger && (Object)(object)((Component)val).GetComponent<BlockTree>() != (Object)null) { num++; } } return num; } private static int CalculateHoneyOutput(int treeCount) { if (treeCount < 3) { return 1; } if (treeCount < 6) { return 2; } return 3; } [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void GetDescriptionPatch(BlockBeeHive __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockBeeHiveRadius")) { int instanceID = ((Object)__instance).GetInstanceID(); targetedThisFrame.Add(instanceID); if (visualizers.TryGetValue(instanceID, out var value)) { value.SetTargeted(targeted: true); } } ConfigManager instance2 = ConfigManager.Instance; if (instance2 == null || instance2.IsPatchEnabled("BlockBeeHive")) { int dayCounter = GetDayCounter(__instance); if (GetHasBee(__instance) && dayCounter < __instance.requiredDays) { int days = __instance.requiredDays - dayCounter; int num = CountTreesAround(__instance); int num2 = CalculateHoneyOutput(num); string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", days); string localizedText = LocalizationManager.Instance.GetLocalizedText("beehive.trees", num); string localizedText2 = LocalizationManager.Instance.GetLocalizedText("beehive.output", num2); string text = localizedDaysWithPrefix + "," + localizedText + "," + localizedText2; __result = ((ItemSO)((Block)__instance).blockSO).GetLocalizedName() + " <i><color=yellow>[" + text + "]</color></i>"; } } } [HarmonyPatch("OnNetworkSpawn")] [HarmonyPostfix] private static void OnNetworkSpawnPatch(BlockBeeHive __instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockBeeHiveRadius")) { GameObject val = new GameObject($"BeeHiveRadius_{((Object)__instance).GetInstanceID()}"); val.transform.SetParent(((Component)__instance).transform); val.transform.localPosition = Vector3.zero; RadiusVisualizer radiusVisualizer = val.AddComponent<RadiusVisualizer>(); radiusVisualizer.Initialize(__instance.treeDetectionRadius); visualizers[((Object)__instance).GetInstanceID()] = radiusVisualizer; } } [HarmonyPatch("OnNetworkDespawn")] [HarmonyPostfix] private static void OnNetworkDespawnPatch(BlockBeeHive __instance) { int instanceID = ((Object)__instance).GetInstanceID(); visualizers.Remove(instanceID); targetedThisFrame.Remove(instanceID); targetedLastFrame.Remove(instanceID); } [HarmonyPatch(typeof(PlayerInventory), "Update")] [HarmonyPostfix] private static void PlayerInventoryUpdatePatch() { ConfigManager instance = ConfigManager.Instance; if ((instance != null && !instance.IsPatchEnabled("BlockBeeHiveRadius")) || Time.frameCount == lastUpdateFrame) { return; } lastUpdateFrame = Time.frameCount; foreach (int item in targetedLastFrame) { if (!targetedThisFrame.Contains(item) && visualizers.TryGetValue(item, out var value)) { value.SetTargeted(targeted: false); } } HashSet<int> hashSet = targetedLastFrame; targetedLastFrame = targetedThisFrame; targetedThisFrame = hashSet; targetedThisFrame.Clear(); } [HarmonyPatch(typeof(PlayerInventory), "HandleNewBlockPlacement")] [HarmonyPostfix] private static void HandleNewBlockPlacementPatch(PlayerInventory __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_010d: Unknown result type (might be due to invalid IL or missing references) ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("BlockBeeHiveRadius")) { return; } GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint == (Object)null) { return; } InventorySlot currentInventorySlot = __instance.GetCurrentInventorySlot(); if (currentInventorySlot.itemId == -1) { return; } ItemSO itemById = GameManager.Instance.GetItemById(currentInventorySlot.itemId); if ((Object)(object)itemById == (Object)null) { return; } BlockSO val = (BlockSO)(object)((itemById is BlockSO) ? itemById : null); if (!((Object)(object)val != (Object)null) || !((Object)(object)((ItemSO)val).prefab.GetComponent<BlockBeeHive>() != (Object)null) || ghostVisualizers.ContainsKey(blockBlueprint)) { return; } int radius = 3; BlockBeeHive component = blockBlueprint.GetComponent<BlockBeeHive>(); if ((Object)(object)component != (Object)null) { radius = component.treeDetectionRadius; } else if ((Object)(object)((ItemSO)val).prefab != (Object)null) { BlockBeeHive component2 = ((ItemSO)val).prefab.GetComponent<BlockBeeHive>(); if ((Object)(object)component2 != (Object)null) { radius = component2.treeDetectionRadius; } } GameObject val2 = new GameObject($"GhostBeeHiveRadius_{((Object)blockBlueprint).GetInstanceID()}"); val2.transform.SetParent(blockBlueprint.transform); val2.transform.localPosition = Vector3.zero; RadiusVisualizer radiusVisualizer = val2.AddComponent<RadiusVisualizer>(); radiusVisualizer.Initialize(radius); radiusVisualizer.SetTargeted(targeted: true); ghostVisualizers[blockBlueprint] = radiusVisualizer; } [HarmonyPatch(typeof(PlayerInventory), "DestroyBlockBlueprint")] [HarmonyPrefix] private static void DestroyBlockBlueprintPatch(PlayerInventory __instance) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockBeeHiveRadius")) { GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint != (Object)null && ghostVisualizers.ContainsKey(blockBlueprint)) { ghostVisualizers.Remove(blockBlueprint); } } } [HarmonyPatch(typeof(PlayerInventory), "OnCurrentSlotChanged")] [HarmonyPrefix] private static void OnCurrentSlotChangedPatch(PlayerInventory __instance) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockBeeHiveRadius")) { GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint != (Object)null && ghostVisualizers.ContainsKey(blockBlueprint)) { ghostVisualizers.Remove(blockBlueprint); } } } } public class RadiusVisualizer : MonoBehaviour { private int radius; private float pulseSpeed = 0.5f; private LineRenderer circleRenderer; private Dictionary<int, LineRenderer> treeConnections = new Dictionary<int, LineRenderer>(); private bool isTargeted; private bool isVisible; private float fadeSpeed = 3f; private float currentAlpha; private float targetAlpha; private float hideDelay = 1f; private float hideDelayTimer; public void Initialize(int radius) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) this.radius = radius; circleRenderer = ((Component)this).gameObject.AddComponent<LineRenderer>(); ((Renderer)circleRenderer).material = new Material(Shader.Find("Sprites/Default")); circleRenderer.startColor = new Color(1f, 0.5f, 0f, 0f); circleRenderer.endColor = new Color(1f, 0.5f, 0f, 0f); circleRenderer.startWidth = 0.05f; circleRenderer.endWidth = 0.05f; circleRenderer.positionCount = 51; circleRenderer.useWorldSpace = true; DrawCircle(); } private void DrawCircle() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = (float)Math.PI / 25f; for (int i = 0; i <= 50; i++) { float num3 = Mathf.Sin(num) * (float)radius; float num4 = Mathf.Cos(num) * (float)radius; Vector3 val = ((Component)this).transform.position + new Vector3(num3, 0.1f, num4); circleRenderer.SetPosition(i, val); num += num2; } } public void SetTargeted(bool targeted) { if (isTargeted != targeted) { isTargeted = targeted; if (targeted) { targetAlpha = 1f; hideDelayTimer = 0f; } else { hideDelayTimer = hideDelay; } } } private void Update() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!isTargeted && hideDelayTimer > 0f) { hideDelayTimer -= Time.deltaTime; if (hideDelayTimer <= 0f) { targetAlpha = 0f; } } if (Mathf.Abs(currentAlpha - targetAlpha) > 0.01f) { currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, fadeSpeed * Time.deltaTime); UpdateVisibility(); } if (currentAlpha <= 0.01f) { if (isVisible) { SetVisibility(visible: false); } return; } if (!isVisible) { SetVisibility(visible: true); } DrawCircle(); float num = 0.7f + Mathf.PingPong(Time.time * pulseSpeed, 0.3f); float num2 = currentAlpha * num; Color val = default(Color); ((Color)(ref val))..ctor(1f, 0.5f, 0f, num2 * 0.3f); circleRenderer.startColor = val; circleRenderer.endColor = val; UpdateTreeConnections(num2); } private void UpdateTreeConnections(float alphaWithPulse) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, (float)radius); HashSet<int> hashSet = new HashSet<int>(); Collider[] array2 = array; Color val2 = default(Color); foreach (Collider val in array2) { if (!val.isTrigger && (Object)(object)((Component)val).GetComponent<BlockTree>() != (Object)null) { int instanceID = ((Object)val).GetInstanceID(); hashSet.Add(instanceID); if (!treeConnections.ContainsKey(instanceID)) { CreateTreeConnection(instanceID, ((Component)val).transform); } else { UpdateTreeConnection(instanceID, ((Component)val).transform); } if (treeConnections.TryGetValue(instanceID, out var value)) { ((Color)(ref val2))..ctor(0f, 1f, 0f, alphaWithPulse * 0.8f); value.startColor = val2; value.endColor = val2; } } } List<int> list = new List<int>(); foreach (int key in treeConnections.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (int item in list) { if ((Object)(object)treeConnections[item] != (Object)null) { Object.Destroy((Object)(object)((Component)treeConnections[item]).gameObject); } treeConnections.Remove(item); } } private void UpdateVisibility() { //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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) Color startColor = circleRenderer.startColor; startColor.a = currentAlpha * 0.3f; circleRenderer.startColor = startColor; circleRenderer.endColor = startColor; Color val = default(Color); ((Color)(ref val))..ctor(0f, 1f, 0f, currentAlpha * 0.8f); foreach (LineRenderer value in treeConnections.Values) { if ((Object)(object)value != (Object)null) { value.startColor = val; value.endColor = val; } } } private void SetVisibility(bool visible) { isVisible = visible; ((Renderer)circleRenderer).enabled = visible; foreach (LineRenderer value in treeConnections.Values) { if ((Object)(object)value != (Object)null) { ((Renderer)value).enabled = visible; } } } private void CreateTreeConnection(int treeId, Transform treeTransform) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"TreeConnection_{treeId}"); val.transform.SetParent(((Component)this).transform); LineRenderer val2 = val.AddComponent<LineRenderer>(); ((Renderer)val2).material = new Material(Shader.Find("Sprites/Default")); val2.startColor = new Color(0f, 1f, 0f, currentAlpha * 0.8f); val2.endColor = new Color(0f, 1f, 0f, currentAlpha * 0.8f); val2.startWidth = 0.04f; val2.endWidth = 0.04f; val2.positionCount = 2; val2.useWorldSpace = true; ((Renderer)val2).enabled = isVisible; val2.SetPosition(0, ((Component)this).transform.position + new Vector3(0f, 0.1f, 0f)); val2.SetPosition(1, treeTransform.position + new Vector3(0f, 0.1f, 0f)); treeConnections[treeId] = val2; } private void UpdateTreeConnection(int treeId, Transform treeTransform) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (treeConnections.ContainsKey(treeId) && (Object)(object)treeConnections[treeId] != (Object)null) { LineRenderer obj = treeConnections[treeId]; obj.SetPosition(0, ((Component)this).transform.position + new Vector3(0f, 0.1f, 0f)); obj.SetPosition(1, treeTransform.position + new Vector3(0f, 0.1f, 0f)); } } private void OnDestroy() { foreach (LineRenderer value in treeConnections.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } treeConnections.Clear(); } } [HarmonyPatch(typeof(BlockCheeseMachine))] public class BlockCheeseMachinePatch { private static readonly FieldInfo currentOutputField = AccessTools.Field(typeof(BlockCheeseMachine), "currentOutput"); private static readonly FieldInfo remainingDaysField = AccessTools.Field(typeof(BlockCheeseMachine), "remainingDays"); private static long GetCurrentOutput(BlockCheeseMachine instance) { object value = currentOutputField.GetValue(instance); return (long)value.GetType().GetProperty("Value").GetValue(value); } private static int GetRemainingDays(BlockCheeseMachine instance) { object value = remainingDaysField.GetValue(instance); return (int)value.GetType().GetProperty("Value").GetValue(value); } [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void GetDescriptionPatch(BlockCheeseMachine __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("BlockCheeseMachine")) { return; } long currentOutput = GetCurrentOutput(__instance); int remainingDays = GetRemainingDays(__instance); if (currentOutput == -1) { return; } ItemSO itemById = GameManager.Instance.GetItemById(currentOutput); if ((Object)(object)itemById != (Object)null) { __result = itemById.GetLocalizedName(); if (remainingDays > 0) { string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", remainingDays); __result = __result + " <i><color=yellow>[" + localizedDaysWithPrefix + "]</color></i>"; } } else { string localizedText = LocalizationManager.Instance.GetLocalizedText("common.unknown_item"); string localizedDaysWithPrefix2 = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", remainingDays); __result = localizedText + " <i><color=yellow>[" + localizedDaysWithPrefix2 + "]</color></i>"; } } } [HarmonyPatch(typeof(BlockDirt))] public class BlockDirtPatch { private static readonly FieldInfo currentSeedField = AccessTools.Field(typeof(BlockDirt), "currentSeed"); [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void Postfix(BlockDirt __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("BlockDirt")) { return; } object value = currentSeedField.GetValue(__instance); long num = (long)value.GetType().GetProperty("Value").GetValue(value); if (num != -1) { ItemSO itemById = GameManager.Instance.GetItemById(num); SeedSO val = (SeedSO)(object)((itemById is SeedSO) ? itemById : null); if (__instance.dayCounter.Value < val.daysToFullGrowth) { int days = val.daysToFullGrowth - __instance.dayCounter.Value; string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", days); __result = __result + " <i><color=yellow>[" + localizedDaysWithPrefix + "]</color></i>"; } } } } [HarmonyPatch(typeof(BlockSprinkler))] public class BlockSprinklerPatch { private static readonly FieldInfo radiusField = AccessTools.Field(typeof(BlockSprinkler), "radius"); private static readonly FieldInfo blockBlueprintField = AccessTools.Field(typeof(PlayerInventory), "blockBlueprint"); private static Dictionary<int, SprinklerRadiusVisualizer> visualizers = new Dictionary<int, SprinklerRadiusVisualizer>(); private static HashSet<int> targetedThisFrame = new HashSet<int>(); private static HashSet<int> targetedLastFrame = new HashSet<int>(); private static int lastUpdateFrame; private static Dictionary<GameObject, SprinklerRadiusVisualizer> ghostVisualizers = new Dictionary<GameObject, SprinklerRadiusVisualizer>(); private static GameObject GetBlockBlueprint(PlayerInventory instance) { object? value = blockBlueprintField.GetValue(instance); return (GameObject)((value is GameObject) ? value : null); } private static float GetRadius(BlockSprinkler instance) { return (float)radiusField.GetValue(instance); } [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void GetDescriptionPatch(BlockSprinkler __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockSprinkler")) { int instanceID = ((Object)__instance).GetInstanceID(); targetedThisFrame.Add(instanceID); if (visualizers.TryGetValue(instanceID, out var value)) { value.SetTargeted(targeted: true); } } } [HarmonyPatch("OnNetworkSpawn")] [HarmonyPostfix] private static void OnNetworkSpawnPatch(BlockSprinkler __instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockSprinkler")) { GameObject val = new GameObject($"SprinklerRadius_{((Object)__instance).GetInstanceID()}"); val.transform.SetParent(((Component)__instance).transform); val.transform.localPosition = Vector3.zero; SprinklerRadiusVisualizer sprinklerRadiusVisualizer = val.AddComponent<SprinklerRadiusVisualizer>(); sprinklerRadiusVisualizer.Initialize(GetRadius(__instance)); visualizers[((Object)__instance).GetInstanceID()] = sprinklerRadiusVisualizer; } } [HarmonyPatch("OnNetworkDespawn")] [HarmonyPostfix] private static void OnNetworkDespawnPatch(BlockSprinkler __instance) { int instanceID = ((Object)__instance).GetInstanceID(); visualizers.Remove(instanceID); targetedThisFrame.Remove(instanceID); targetedLastFrame.Remove(instanceID); } [HarmonyPatch(typeof(PlayerInventory), "Update")] [HarmonyPostfix] private static void PlayerInventoryUpdatePatch() { ConfigManager instance = ConfigManager.Instance; if ((instance != null && !instance.IsPatchEnabled("BlockSprinkler")) || Time.frameCount == lastUpdateFrame) { return; } lastUpdateFrame = Time.frameCount; foreach (int item in targetedLastFrame) { if (!targetedThisFrame.Contains(item) && visualizers.TryGetValue(item, out var value)) { value.SetTargeted(targeted: false); } } HashSet<int> hashSet = targetedLastFrame; targetedLastFrame = targetedThisFrame; targetedThisFrame = hashSet; targetedThisFrame.Clear(); } [HarmonyPatch(typeof(PlayerInventory), "HandleNewBlockPlacement")] [HarmonyPostfix] private static void HandleNewBlockPlacementPatch(PlayerInventory __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0111: Unknown result type (might be due to invalid IL or missing references) ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("BlockSprinkler")) { return; } GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint == (Object)null) { return; } InventorySlot currentInventorySlot = __instance.GetCurrentInventorySlot(); if (currentInventorySlot.itemId == -1) { return; } ItemSO itemById = GameManager.Instance.GetItemById(currentInventorySlot.itemId); if ((Object)(object)itemById == (Object)null) { return; } BlockSO val = (BlockSO)(object)((itemById is BlockSO) ? itemById : null); if (!((Object)(object)val != (Object)null) || !((Object)(object)((ItemSO)val).prefab.GetComponent<BlockSprinkler>() != (Object)null) || ghostVisualizers.ContainsKey(blockBlueprint)) { return; } float radius = 2f; BlockSprinkler component = blockBlueprint.GetComponent<BlockSprinkler>(); if ((Object)(object)component != (Object)null) { radius = GetRadius(component); } else if ((Object)(object)((ItemSO)val).prefab != (Object)null) { BlockSprinkler component2 = ((ItemSO)val).prefab.GetComponent<BlockSprinkler>(); if ((Object)(object)component2 != (Object)null) { radius = GetRadius(component2); } } GameObject val2 = new GameObject($"GhostSprinklerRadius_{((Object)blockBlueprint).GetInstanceID()}"); val2.transform.SetParent(blockBlueprint.transform); val2.transform.localPosition = Vector3.zero; SprinklerRadiusVisualizer sprinklerRadiusVisualizer = val2.AddComponent<SprinklerRadiusVisualizer>(); sprinklerRadiusVisualizer.Initialize(radius); sprinklerRadiusVisualizer.SetTargeted(targeted: true); ghostVisualizers[blockBlueprint] = sprinklerRadiusVisualizer; } [HarmonyPatch(typeof(PlayerInventory), "DestroyBlockBlueprint")] [HarmonyPrefix] private static void DestroyBlockBlueprintPatch(PlayerInventory __instance) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockSprinkler")) { GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint != (Object)null && ghostVisualizers.ContainsKey(blockBlueprint)) { ghostVisualizers.Remove(blockBlueprint); } } } [HarmonyPatch(typeof(PlayerInventory), "OnCurrentSlotChanged")] [HarmonyPrefix] private static void OnCurrentSlotChangedPatch(PlayerInventory __instance) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockSprinkler")) { GameObject blockBlueprint = GetBlockBlueprint(__instance); if ((Object)(object)blockBlueprint != (Object)null && ghostVisualizers.ContainsKey(blockBlueprint)) { ghostVisualizers.Remove(blockBlueprint); } } } } public class SprinklerRadiusVisualizer : MonoBehaviour { private float radius; private float pulseSpeed = 0.5f; private LineRenderer circleRenderer; private bool isTargeted; private bool isVisible; private float fadeSpeed = 3f; private float currentAlpha; private float targetAlpha; private float hideDelay = 1f; private float hideDelayTimer; public void Initialize(float radius) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) this.radius = radius; circleRenderer = ((Component)this).gameObject.AddComponent<LineRenderer>(); ((Renderer)circleRenderer).material = new Material(Shader.Find("Sprites/Default")); circleRenderer.startColor = new Color(0f, 0.7f, 1f, 0f); circleRenderer.endColor = new Color(0f, 0.7f, 1f, 0f); circleRenderer.startWidth = 0.05f; circleRenderer.endWidth = 0.05f; circleRenderer.positionCount = 51; circleRenderer.useWorldSpace = true; DrawCircle(); } private void DrawCircle() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = (float)Math.PI / 25f; for (int i = 0; i <= 50; i++) { float num3 = Mathf.Sin(num) * radius; float num4 = Mathf.Cos(num) * radius; Vector3 val = ((Component)this).transform.position + new Vector3(num3, 0.1f, num4); circleRenderer.SetPosition(i, val); num += num2; } } public void SetTargeted(bool targeted) { if (isTargeted != targeted) { isTargeted = targeted; if (targeted) { targetAlpha = 1f; hideDelayTimer = 0f; } else { hideDelayTimer = hideDelay; } } } private void Update() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!isTargeted && hideDelayTimer > 0f) { hideDelayTimer -= Time.deltaTime; if (hideDelayTimer <= 0f) { targetAlpha = 0f; } } if (Mathf.Abs(currentAlpha - targetAlpha) > 0.01f) { currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, fadeSpeed * Time.deltaTime); UpdateVisibility(); } if (currentAlpha <= 0.01f) { if (isVisible) { SetVisibility(visible: false); } return; } if (!isVisible) { SetVisibility(visible: true); } DrawCircle(); float num = 0.7f + Mathf.PingPong(Time.time * pulseSpeed, 0.3f); float num2 = currentAlpha * num; Color val = default(Color); ((Color)(ref val))..ctor(0f, 0.7f, 1f, num2 * 0.3f); circleRenderer.startColor = val; circleRenderer.endColor = val; } private void UpdateVisibility() { //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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Color startColor = circleRenderer.startColor; startColor.a = currentAlpha * 0.3f; circleRenderer.startColor = startColor; circleRenderer.endColor = startColor; } private void SetVisibility(bool visible) { isVisible = visible; ((Renderer)circleRenderer).enabled = visible; } } [HarmonyPatch(typeof(BlockTree))] public class BlockTreePatch { private static readonly FieldInfo treeSOField = AccessTools.Field(typeof(BlockTree), "treeSO"); [HarmonyPatch("GetDescription")] [HarmonyPostfix] private static void Postfix(BlockTree __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("BlockTree")) { object? value = treeSOField.GetValue(__instance); TreeSO val = (TreeSO)((value is TreeSO) ? value : null); if (__instance.dayCounter.Value < val.daysToHarvestAfterGrowth) { int days = val.daysToHarvestAfterGrowth - __instance.dayCounter.Value; string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("common.remaining_prefix", days); __result = __result + " <i><color=yellow>[" + localizedDaysWithPrefix + "]</color></i>"; } } } } [HarmonyPatch(typeof(DockOrderTile))] public class DockOrderTilePatch { [HarmonyPatch("SetData")] [HarmonyPostfix] private static void SetDataPatch(DockOrderTile __instance, ProductSO productSO) { ConfigManager instance = ConfigManager.Instance; if ((instance == null || instance.IsPatchEnabled("DockOrderTile")) && BetterDockOrderCompatibility.ShouldShowInventoryHint()) { int productAmount = GetProductAmount(productSO); TextMeshProUGUI textTitle = __instance.textTitle; string localizedText = LocalizationManager.Instance.GetLocalizedText("order.inventory", productAmount); ((TMP_Text)textTitle).text = ((TMP_Text)textTitle).text + $" <color=yellow>[{localizedText}]</color>"; } } public static int GetProductAmount(ProductSO product) { return (from x in Object.FindObjectsOfType<Item>() where x.itemSO is ProductSO && x.itemSO.itemName == ((ItemSO)product).itemName select x).Sum((Item item) => item.amount.Value); } } [HarmonyPatch] public static class HorseCargoTooltipPatch { [HarmonyPatch(typeof(HorseCargo), "GetDescription")] [HarmonyPostfix] public static void HorseCargo_GetDescription_Postfix(HorseCargo __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if ((instance != null && !instance.IsPatchEnabled("HorseCargoTooltip")) || string.IsNullOrEmpty(__result)) { return; } Horse horse = __instance.horse; if (!((Object)(object)horse == (Object)null) && horse.slots != null) { int usedSlotsCount = GetUsedSlotsCount(horse); int count = horse.slots.Count; string text = LocalizationManager.Instance?.GetLocalizedText("horse.cargo_info", usedSlotsCount, count); if (horse.IsFull()) { string text2 = LocalizationManager.Instance?.GetLocalizedText("horse.cargo_full"); text = text + " " + text2; } __result = $"{__result}\n{text}"; } } [HarmonyPatch(typeof(Horse), "GetDescription")] [HarmonyPostfix] public static void Horse_GetDescription_Postfix(Horse __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if ((instance == null || instance.IsPatchEnabled("HorseCargoTooltip")) && __instance.slots != null) { int usedSlotsCount = GetUsedSlotsCount(__instance); int count = __instance.slots.Count; string text = LocalizationManager.Instance?.GetLocalizedText("horse.cargo_info", usedSlotsCount, count); if (__instance.IsFull()) { string text2 = LocalizationManager.Instance?.GetLocalizedText("horse.cargo_full"); text = text + " " + text2; } if (string.IsNullOrEmpty(__result)) { __result = text; } else { __result = $"{__result}\n{text}"; } } } private static int GetUsedSlotsCount(Horse horse) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (horse?.slots == null) { return 0; } int num = 0; for (int i = 0; i < horse.slots.Count; i++) { if (horse.slots[i].itemId != -1) { num++; } } return num; } } [HarmonyPatch(typeof(PlayerInventory))] public class PlayerInventoryPatch { private static readonly HashSet<string> AllowPlacementAnywhere = new HashSet<string> { "floor_sign", "wall_sign", "big_fence", "chandelier", "lantern", "small_fence", "wall_candle", "paper_lantern_1", "paper_lantern_2", "paper_lantern_3", "paper_lantern_4", "golden_candle" }; private static readonly FieldRef<PlayerInventory, GameObject> blockBlueprint = AccessTools.FieldRefAccess<PlayerInventory, GameObject>("blockBlueprint"); private static readonly FieldRef<PlayerInventory, GameObject> itemBlueprint = AccessTools.FieldRefAccess<PlayerInventory, GameObject>("itemBlueprint"); private static readonly FieldRef<PlayerInventory, int> activeSlots = AccessTools.FieldRefAccess<PlayerInventory, int>("activeSlots"); [HarmonyPatch(typeof(PlayerInventory), "HandleItemPlacement")] [HarmonyPrefix] public static bool PatchItemRotation(PlayerInventory __instance) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("PlayerInventoryRotation")) { return true; } GameObject val = itemBlueprint.Invoke(__instance); if ((Object)(object)val == (Object)null) { return true; } PlayerActions player = InputManager.Instance.inputMaster.Player; if (((PlayerActions)(ref player)).Rotate.WasPerformedThisFrame()) { LeanTweenExt.LeanRotateAroundLocal(val, Vector3.up, 45f, 0.1f); return false; } return true; } [HarmonyPatch("HandleNewBlockPlacement")] [HarmonyPrefix] public static bool HandleNewBlockPlacementPatch(PlayerInventory __instance) { //IL_000a: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Expected O, but got Unknown //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_056c: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_0631: Unknown result type (might be due to invalid IL or missing references) //IL_0636: Unknown result type (might be due to invalid IL or missing references) //IL_066d: Unknown result type (might be due to invalid IL or missing references) //IL_0679: Unknown result type (might be due to invalid IL or missing references) //IL_067e: Unknown result type (might be due to invalid IL or missing references) try { PlayerActions player = InputManager.Instance.inputMaster.Player; if (((PlayerActions)(ref player)).Place.IsPressed() || (Object)(object)itemBlueprint.Invoke(__instance) != (Object)null) { return true; } InventorySlot currentInventorySlot = __instance.GetCurrentInventorySlot(); if (currentInventorySlot.itemId == -1) { return true; } ItemSO itemById = GameManager.Instance.GetItemById(currentInventorySlot.itemId); BlockSO val = (BlockSO)(object)((itemById is BlockSO) ? itemById : null); if ((Object)(object)val == (Object)null) { return true; } ConfigManager instance = ConfigManager.Instance; bool flag = (instance == null || instance.IsPatchEnabled("PlayerInventoryFreePlacement")) && AllowPlacementAnywhere.Contains(((ItemSO)val).itemName); Ray val2 = ((Camera)AccessTools.Field(typeof(PlayerInventory), "playerCamera").GetValue(__instance)).ViewportPointToRay(Vector3.one / 2f); LayerMask val3 = LayerMask.op_Implicit(~LayerMask.op_Implicit(__instance.blockIgnoredLayerMask)); LayerMask.op_Implicit(flag ? (-1) : (-1 & LayerMask.op_Implicit(val3))); QueryTriggerInteraction val4 = (QueryTriggerInteraction)1; int num = 1; if (((ItemSO)val).prefab.CompareTag("Boat") || ((ItemSO)val).prefab.CompareTag("Floatable")) { val4 = (QueryTriggerInteraction)2; num = 2; } RaycastHit val5 = default(RaycastHit); if (Physics.Raycast(val2, ref val5, __instance.buildDistance * (float)num, flag ? (-1) : (-1 & LayerMask.op_Implicit(val3)), val4)) { if (!flag && !LayerMaskExtensions.Includes(val.placementLayerMask, ((Component)((RaycastHit)(ref val5)).collider).gameObject.layer)) { AccessTools.Method(typeof(PlayerInventory), "DestroyBlockBlueprint", (Type[])null, (Type[])null).Invoke(__instance, null); return false; } GameObject val6 = blockBlueprint.Invoke(__instance); if ((Object)(object)val6 == (Object)null) { Quaternion rotation = ((RaycastHit)(ref val5)).transform.rotation; string text = LayerMask.LayerToName(((Component)((RaycastHit)(ref val5)).collider).gameObject.layer); if (GameManager.Instance.mapSO.id == 0 && (text == "Water" || text == "Terrain")) { ((Quaternion)(ref rotation)).eulerAngles = new Vector3(((Quaternion)(ref rotation)).eulerAngles.x, ((Quaternion)(ref rotation)).eulerAngles.y - 28.85f, ((Quaternion)(ref rotation)).eulerAngles.z); } AccessTools.Field(typeof(PlayerInventory), "blockBlueprint").SetValue(__instance, Object.Instantiate<GameObject>(((ItemSO)val).prefab, ((RaycastHit)(ref val5)).point, rotation)); AccessTools.Field(typeof(PlayerInventory), "blockBlueprintHit").SetValue(__instance, ((RaycastHit)(ref val5)).transform); GameObject val7 = blockBlueprint.Invoke(__instance); Collider[] componentsInChildren = val7.GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } val7.GetComponent<NetworkObject>().AutoObjectParentSync = false; BoxCollider blueprintTrigger = val7.GetComponent<Block>().blueprintTrigger; AccessTools.Field(typeof(PlayerInventory), "blueprintTrigger").SetValue(__instance, blueprintTrigger); ((Component)blueprintTrigger).gameObject.layer = LayerMask.NameToLayer("IgnoreBlockCollision"); ObstacleColliderVisualizer val8 = default(ObstacleColliderVisualizer); if (((Component)blueprintTrigger).TryGetComponent<ObstacleColliderVisualizer>(ref val8)) { ((Behaviour)val8).enabled = true; } if ((Object)(object)blueprintTrigger != (Object)null) { ((Collider)blueprintTrigger).enabled = true; } AccessTools.Field(typeof(PlayerInventory), "meshRenderersBlockBlueprint").SetValue(__instance, val7.GetComponentsInChildren<MeshRenderer>().ToList()); AccessTools.Method(typeof(PlayerInventory), "ShowObstacleVisualizers", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { true }); return false; } val6.transform.position = ((RaycastHit)(ref val5)).point; if ((Object)(Transform)AccessTools.Field(typeof(PlayerInventory), "blockBlueprintHit").GetValue(__instance) != (Object)(object)((RaycastHit)(ref val5)).transform) { AccessTools.Field(typeof(PlayerInventory), "blockBlueprintHit").SetValue(__instance, ((RaycastHit)(ref val5)).transform); string text2 = LayerMask.LayerToName(((Component)((RaycastHit)(ref val5)).collider).gameObject.layer); Quaternion rotation2 = ((RaycastHit)(ref val5)).transform.rotation; if (GameManager.Instance.mapSO.id == 0 && (text2 == "Water" || text2 == "Terrain")) { ((Quaternion)(ref rotation2)).eulerAngles = new Vector3(((Quaternion)(ref rotation2)).eulerAngles.x, ((Quaternion)(ref rotation2)).eulerAngles.y - 28.85f, ((Quaternion)(ref rotation2)).eulerAngles.z); } val6.transform.rotation = rotation2; } bool flag2 = ConfigManager.Instance?.IsPatchEnabled("PlayerInventoryRotation") ?? true; player = InputManager.Instance.inputMaster.Player; if (((PlayerActions)(ref player)).Rotate.WasPerformedThisFrame() && !val.disableRotation) { if (flag2) { LeanTweenExt.LeanRotateAroundLocal(val6, Vector3.up, 45f, 0.1f); } else { val6.transform.Rotate(Vector3.up, 90f); } } bool flag3 = true; BoxCollider val9 = (BoxCollider)AccessTools.Field(typeof(PlayerInventory), "blueprintTrigger").GetValue(__instance); if ((Object)(object)val9 == (Object)null) { Debug.LogError((object)"Block needs a blueprint collider!"); } else { Vector3 val10 = Vector3.Scale(val9.size, ((Component)val9).transform.lossyScale) / 2f; Bounds bounds = ((Collider)val9).bounds; flag3 = Physics.CheckBox(((Bounds)(ref bounds)).center, val10, ((Component)val9).transform.rotation, LayerMask.op_Implicit(val3), (QueryTriggerInteraction)2); } List<MeshRenderer> obj = (List<MeshRenderer>)AccessTools.Field(typeof(PlayerInventory), "meshRenderersBlockBlueprint").GetValue(__instance); Material val11 = (flag3 ? __instance.materialBlueprintInvalid : __instance.materialBlueprintValid); foreach (MeshRenderer item in obj) { int num2 = ((Renderer)item).sharedMaterials.Length; Material[] array = (Material[])(object)new Material[num2]; for (int j = 0; j < num2; j++) { array[j] = val11; } ((Renderer)item).materials = array; } if (flag3) { return false; } player = InputManager.Instance.inputMaster.Player; if (((PlayerActions)(ref player)).Put.WasPerformedThisFrame()) { __instance.audioSource.PlayOneShot(__instance.placementSound, 0.2f); __instance.PlaceBlockServerRpc(((ItemSO)val).id, val6.transform.position, val6.transform.rotation, currentInventorySlot.dayCounter); __instance.UseItem(); AccessTools.Method(typeof(PlayerInventory), "DestroyBlockBlueprint", (Type[])null, (Type[])null).Invoke(__instance, null); return false; } } else { AccessTools.Method(typeof(PlayerInventory), "DestroyBlockBlueprint", (Type[])null, (Type[])null).Invoke(__instance, null); } return false; } catch (Exception ex) { BetterMarketPlus.Logger.LogError((object)("方块放置错误: " + ex.Message + "\n" + ex.StackTrace)); return true; } } } [HarmonyPatch] public class TreeMovePatch { private struct TreeStateData { public int dayCounter; public int currentTotalHarvestAmount; public int harvestCount; public bool hasBeeHive; public bool isWatered; } [CompilerGenerated] private sealed class <ProcessTreeItemStateCoroutine>d__13 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector3 position; public int encodedPrice; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessTreeItemStateCoroutine>d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0059: 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) //IL_008b: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 2; return true; case 2: { <>1__state = -1; Collider[] array = Physics.OverlapSphere(position, 2f); for (int i = 0; i < array.Length; i++) { Item component = ((Component)array[i]).GetComponent<Item>(); if ((Object)(object)component != (Object)null && Vector3.Distance(((Component)component).transform.position, position) < 1.5f) { if (itemIdField.GetValue(component) is NetworkVariable<long> val && GameManager.Instance.GetItemById(val.Value) is TreeSO) { StoreTreeStateInItem(component, encodedPrice); } break; } } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RestoreTreeStateCoroutine>d__16 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public int encodedPrice; public int dayCounter; public Vector3 position; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreTreeStateCoroutine>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForFixedUpdate(); <>1__state = 2; return true; case 2: { <>1__state = -1; TreeStateData treeState = DecodeTreeStateFromPrice(encodedPrice, dayCounter); Collider[] array = Physics.OverlapSphere(position, 1f); for (int i = 0; i < array.Length; i++) { BlockTree component = ((Component)array[i]).GetComponent<BlockTree>(); if ((Object)(object)component != (Object)null && Vector3.Distance(((Component)component).transform.position, position) < 0.5f) { if (((NetworkBehaviour)component).IsServer) { RestoreFullTreeState(component, treeState); } break; } } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly FieldInfo treSOField = AccessTools.Field(typeof(BlockTree), "treeSO"); private static readonly FieldInfo itemIdField = AccessTools.Field(typeof(Item), "itemId"); private static readonly FieldInfo localPlayerInventoryField = AccessTools.Field(typeof(BlockTree), "localPlayerInventory"); private static readonly FieldInfo beeHiveField = AccessTools.Field(typeof(BlockTree), "beeHive"); private static readonly FieldInfo isWateredField = AccessTools.Field(typeof(BlockTree), "isWatered"); [HarmonyPatch(typeof(BlockTree), "UseTool")] [HarmonyPrefix] private static bool UseTool_Prefix(BlockTree __instance, Vector3 hitPosition) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("TreeMove")) { return true; } object? value = localPlayerInventoryField.GetValue(__instance); PlayerInventory val = (PlayerInventory)((value is PlayerInventory) ? value : null); if ((Object)(object)val == (Object)null) { return true; } ItemSO currentItemSO = val.GetCurrentItemSO(); ToolSO val2 = (ToolSO)(object)((currentItemSO is ToolSO) ? currentItemSO : null); if ((Object)(object)val2 == (Object)null) { return true; } if (!(AccessTools.Field(typeof(BlockTree), "hoes").GetValue(__instance) is List<ToolSO> list)) { return true; } if (list.Contains(val2) && IsShiftPressed()) { if (((NetworkBehaviour)__instance).IsServer) { PerformLosslessTreeMoving(__instance); } return false; } return true; } private static bool IsShiftPressed() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)InputManager.Instance != (Object)null && InputManager.Instance.inputMaster != null) { PlayerActions player = InputManager.Instance.inputMaster.Player; return ((PlayerActions)(ref player)).Sprint.IsPressed(); } return false; } private static void PerformLosslessTreeMoving(BlockTree treeInstance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) object? value = treSOField.GetValue(treeInstance); TreeSO val = (TreeSO)((value is TreeSO) ? value : null); if (!((Object)(object)val == (Object)null)) { TreeStateData state = ExtractTreeState(treeInstance); treeInstance.HarvestEffectsClientRpc(); Vector3 val2 = ((Component)treeInstance).transform.position + new Vector3(0f, 0.5f, 0f); GameManager.Instance.SpawnItemAtPositionServerRpc(((ItemSO)val).id, val2, true, 1, EncodeTreeStateToPrice(state), state.dayCounter); ((NetworkBehaviour)treeInstance).NetworkObject.Despawn(true); } } private static TreeStateData ExtractTreeState(BlockTree treeInstance) { object? value = beeHiveField.GetValue(treeInstance); GameObject val = (GameObject)((value is GameObject) ? value : null); bool isWatered = (isWateredField.GetValue(treeInstance) as NetworkVariable<bool>)?.Value ?? false; TreeStateData result = default(TreeStateData); result.dayCounter = treeInstance.dayCounter.Value; result.currentTotalHarvestAmount = treeInstance.currentTotalHarvestAmount.Value; result.harvestCount = treeInstance.harvestCount.Value; result.hasBeeHive = (Object)(object)val != (Object)null; result.isWatered = isWatered; return result; } private static int EncodeTreeStateToPrice(TreeStateData state) { int num = 0; num |= state.currentTotalHarvestAmount & 0xFFFF; num |= (state.harvestCount & 0x3FFF) << 16; if (state.hasBeeHive) { num |= 0x40000000; } if (state.isWatered) { num |= int.MinValue; } return num; } private static TreeStateData DecodeTreeStateFromPrice(int encodedPrice, int dayCounter) { TreeStateData result = default(TreeStateData); result.dayCounter = dayCounter; result.currentTotalHarvestAmount = encodedPrice & 0xFFFF; result.harvestCount = (encodedPrice >> 16) & 0x3FFF; result.hasBeeHive = (encodedPrice & 0x40000000) != 0; result.isWatered = (encodedPrice & int.MinValue) != 0; return result; } [HarmonyPatch(typeof(GameManager), "SpawnItemAtPositionServerRpc", new Type[] { typeof(long), typeof(Vector3), typeof(bool), typeof(int), typeof(int), typeof(int) })] [HarmonyPostfix] private static void SpawnItemAtPositionServerRpc_Postfix(long itemId, Vector3 position, bool enableRigidbodyOnSpawn, int amount, int cost, int dayCounter) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (dayCounter > 0 && cost != 0) { ItemSO itemById = GameManager.Instance.GetItemById(itemId); if (!((Object)(object)itemById == (Object)null) && itemById is TreeSO) { ((MonoBehaviour)GameManager.Instance).StartCoroutine(ProcessTreeItemStateCoroutine(position, cost, dayCounter)); } } } [IteratorStateMachine(typeof(<ProcessTreeItemStateCoroutine>d__13))] private static IEnumerator ProcessTreeItemStateCoroutine(Vector3 position, int encodedPrice, int dayCounter) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ProcessTreeItemStateCoroutine>d__13(0) { position = position, encodedPrice = encodedPrice }; } private static void StoreTreeStateInItem(Item item, int encodedPrice) { FieldInfo fieldInfo = AccessTools.Field(typeof(Item), "cost"); if (fieldInfo != null) { fieldInfo.SetValue(item, encodedPrice); } } [HarmonyPatch(typeof(PlayerInventory), "PlaceBlockServerRpc")] [HarmonyPostfix] private static void PlaceBlockServerRpc_Postfix(long itemId, Vector3 position, Quaternion rotation, int dayCounter) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (dayCounter <= 0) { return; } ItemSO itemById = GameManager.Instance.GetItemById(itemId); BlockSO val = (BlockSO)(object)((itemById is BlockSO) ? itemById : null); if ((Object)(object)val == (Object)null || !(val is TreeSO)) { return; } PlayerInventory val2 = Object.FindObjectOfType<PlayerInventory>(); if ((Object)(object)val2 != (Object)null) { InventorySlot currentInventorySlot = val2.GetCurrentInventorySlot(); if (currentInventorySlot.itemId == itemId) { ((MonoBehaviour)GameManager.Instance).StartCoroutine(RestoreTreeStateCoroutine(position, dayCounter, currentInventorySlot.cost)); } } } [IteratorStateMachine(typeof(<RestoreTreeStateCoroutine>d__16))] private static IEnumerator RestoreTreeStateCoroutine(Vector3 position, int dayCounter, int encodedPrice) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestoreTreeStateCoroutine>d__16(0) { position = position, dayCounter = dayCounter, encodedPrice = encodedPrice }; } private static void RestoreFullTreeState(BlockTree blockTree, TreeStateData treeState) { blockTree.dayCounter.Value = treeState.dayCounter; blockTree.currentTotalHarvestAmount.Value = treeState.currentTotalHarvestAmount; blockTree.harvestCount.Value = treeState.harvestCount; if (isWateredField.GetValue(blockTree) is NetworkVariable<bool> val) { val.Value = treeState.isWatered; } object? value = beeHiveField.GetValue(blockTree); GameObject val2 = (GameObject)((value is GameObject) ? value : null); if (treeState.hasBeeHive && (Object)(object)val2 == (Object)null) { AccessTools.Method(typeof(BlockTree), "SpawnBeeHive", (Type[])null, (Type[])null)?.Invoke(blockTree, null); } } [HarmonyPatch(typeof(Item), "GetDescription")] [HarmonyPostfix] private static void GetDescription_Postfix(Item __instance, ref string __result) { if (__instance.dayCounter.Value <= 0 || !(itemIdField.GetValue(__instance) is NetworkVariable<long> val)) { return; } ItemSO itemById = GameManager.Instance.GetItemById(val.Value); TreeSO val2 = (TreeSO)(object)((itemById is TreeSO) ? itemById : null); if (val2 == null) { return; } int value = __instance.dayCounter.Value; string key = "tree.stage.seedling"; if (value >= val2.daysToHarvestAfterGrowth) { key = "tree.stage.mature"; } else if (value >= val2.daysToFullGrowth) { key = "tree.stage.adult"; } else if (value >= val2.daysToHalfGrowth) { key = "tree.stage.growing"; } string localizedText = LocalizationManager.Instance.GetLocalizedText(key); string localizedDays = LocalizationManager.Instance.GetLocalizedDays(value); string localizedText2 = LocalizationManager.Instance.GetLocalizedText("tree.growth_info", localizedDays, localizedText); FieldInfo fieldInfo = AccessTools.Field(typeof(Item), "cost"); if (fieldInfo != null) { int num = (int)fieldInfo.GetValue(__instance); if (num != 0) { TreeStateData treeStateData = DecodeTreeStateFromPrice(num, value); string text = ""; if (value >= val2.daysToHarvestAfterGrowth && val2.totalHarvestAmount > 0 && treeStateData.currentTotalHarvestAmount > 0 && treeStateData.currentTotalHarvestAmount < val2.totalHarvestAmount) { float num2 = (float)(val2.totalHarvestAmount - treeStateData.currentTotalHarvestAmount) / (float)val2.totalHarvestAmount * 100f; string localizedText3 = LocalizationManager.Instance.GetLocalizedText("tree.status.harvest_progress", num2.ToString("F0")); text = text + ", " + localizedText3; } if (treeStateData.hasBeeHive) { string localizedText4 = LocalizationManager.Instance.GetLocalizedText("tree.status.has_beehive"); text = text + ", " + localizedText4; } __result = __result + " <i><color=yellow>[" + localizedText2 + text + "]</color></i>"; } else { __result = __result + " <i><color=yellow>[" + localizedText2 + "]</color></i>"; } } else { __result = __result + " <i><color=yellow>[" + localizedText2 + "]</color></i>"; } } [HarmonyPatch(typeof(BlockTree), "GetDescription")] [HarmonyPostfix] private static void AddTreeMoveHint_Postfix(BlockTree __instance, ref string __result) { ConfigManager instance = ConfigManager.Instance; if (instance == null || instance.IsPatchEnabled("TreeMove")) { string localizedText = LocalizationManager.Instance.GetLocalizedText("tree.move_hint"); __result = __result + "\n<size=10><color=yellow>" + localizedText + "</color></size>"; } } } [HarmonyPatch(typeof(UIManager))] public class UIManagerCoinTooltipPatch { private static readonly FieldInfo dailyTransactionsField; static UIManagerCoinTooltipPatch() { dailyTransactionsField = AccessTools.Field(typeof(GameManager), "dailyTransactions"); BetterMarketEvents.OnTransactionAdded += RefreshCoinTooltip; } private static void RefreshCoinTooltip() { if ((Object)(object)UIManager.Instance != (Object)null && (Object)(object)GameManager.Instance != (Object)null) { UIManager.Instance.SetCoinTooltip(GameManager.Instance.GetBankruptcyDayCounterValue(), GameManager.Instance.maxDaysForBankruptcy); } } [HarmonyPatch("SetCoinTooltip")] [HarmonyPostfix] private static void SetCoinTooltipPatch(UIManager __instance) { //IL_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected I4, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("UIManagerCoinTooltip")) { return; } string text = ""; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; if (dailyTransactionsField.GetValue(GameManager.Instance) is List<Transaction> list) { foreach (Transaction item in list) { TransactionType transactionType = item.TransactionType; switch ((int)transactionType) { case 0: num += item.Amount; break; case 5: num4 += item.Amount; break; case 4: num2 += item.Amount; break; case 3: num3 += item.Amount; break; case 1: num5 += item.Amount; break; case 6: num6 += item.Amount; break; } } } int rent = GameManager.Instance.GetRent(); int maintenanceValue = GameManager.Instance.GetMaintenanceValue(); if (num2 == 0) { num2 = -rent; } if (num3 == 0) { num3 = -maintenanceValue; } int num7 = Math.Abs(num2) + Math.Abs(num3); if (num4 < 0) { num7 += Math.Abs(num4); } int num8 = num7; if (num5 < 0) { num8 += Math.Abs(num5); } if (num6 < 0) { num8 += Math.Abs(num6); } int num9 = num - num8; int num10 = GameManager.Instance.initialTaxPercentage; EventSO currentEvent = GameManager.Instance.GetCurrentEvent(); if ((Object)(object)currentEvent != (Object)null) { num10 = Mathf.RoundToInt((float)num10 * currentEvent.taxMultiplier); } int num11 = Mathf.RoundToInt((float)Math.Max(0, num9) * ((float)num10 / 100f)); int num12 = num9 - num11; int num13 = num8 + num11; text += string.Format("\n<color=#8A5125>{0}</color>\n{1} C", LocalizationManager.Instance.GetLocalizedText("financial.sales"), num); text += string.Format("\n<color=#8A5125>{0}</color>\n{1}%", LocalizationManager.Instance.GetLocalizedText("financial.current_tax_rate"), num10); string arg = ((num11 > 0) ? "-" : ""); text += string.Format("\n<color=#8A5125>{0}</color>\n{1}{2} C", LocalizationManager.Instance.GetLocalizedText("financial.tax"), arg, num11); string arg2 = ((num12 >= 0) ? "+" : ""); text += string.Format("\n<color=#8A5125>{0}</color>\n{1}{2} C", LocalizationManager.Instance.GetLocalizedText("financial.net_profit"), arg2, num12); string arg3 = ((num13 > 0) ? "-" : ""); text += string.Format("\n<color=#8A5125>{0}</color>\n{1}{2} C", LocalizationManager.Instance.GetLocalizedText("financial.total_expenses"), arg3, num13); TooltipTrigger tooltipTriggerCoins = __instance.tooltipTriggerCoins; tooltipTriggerCoins.content += text; } } [HarmonyPatch(typeof(GameManager))] [HarmonyPatch("IncrementCoinsServer")] public class GameManagerTransactionPatch { [HarmonyPostfix] private static void IncrementCoinsServerPatch(GameManager __instance, int value, TransactionType type, string desc) { BetterMarketEvents.TriggerTransactionAdded(); } } public static class BetterMarketEvents { public static event Action OnTransactionAdded; public static void TriggerTransactionAdded() { BetterMarketEvents.OnTransactionAdded?.Invoke(); } } [HarmonyPatch(typeof(UIManager))] public class UIManagerRecipePatch { [HarmonyPatch("OpenRecipesPanel")] [HarmonyPrefix] private static void OpenRecipesPanelPrefix(UIManager __instance) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("UIManagerRecipe")) { return; } Transform listRecipes = __instance.listRecipes; if ((Object)(object)listRecipes != (Object)null && listRecipes.childCount > 0) { for (int num = listRecipes.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)listRecipes.GetChild(num)).gameObject); } } } [HarmonyPatch("OpenRecipesPanel")] [HarmonyPostfix] private static void OpenRecipesPanelPatch(UIManager __instance, List<RecipeSO> recipes) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("UIManagerRecipe")) { return; } Transform listRecipes = __instance.listRecipes; if ((Object)(object)listRecipes == (Object)null) { return; } for (int i = 0; i < listRecipes.childCount; i++) { if (i >= recipes.Count) { continue; } ListButton component = ((Component)listRecipes.GetChild(i)).gameObject.GetComponent<ListButton>(); if ((Object)(object)component == (Object)null) { continue; } TextMeshProUGUI textTitle = component.textTitle; if ((Object)(object)textTitle == (Object)null) { continue; } RecipeSO val = recipes[i]; if (!((Object)(object)val == (Object)null) && val.requiredDays > 0) { string text = ((TMP_Text)textTitle).text; int num = text.IndexOf("\n<color=yellow>"); if (num > 0) { text = text.Substring(0, num); } string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("recipe.required_prefix", val.requiredDays); ((TMP_Text)textTitle).text = text + "\n<color=yellow>" + localizedDaysWithPrefix + "</color>"; } } } [HarmonyPatch("UpdateRecipeIngredients")] [HarmonyPostfix] private static void UpdateRecipeIngredientsPatch(UIManager __instance, RecipeSO recipeSO) { ConfigManager instance = ConfigManager.Instance; if ((instance != null && !instance.IsPatchEnabled("UIManagerRecipe")) || (Object)(object)recipeSO == (Object)null || recipeSO.requiredDays <= 0) { return; } TextMeshProUGUI textRecipeOutput = __instance.textRecipeOutput; if (!((Object)(object)textRecipeOutput == (Object)null)) { string text = ((TMP_Text)textRecipeOutput).text; int num = text.IndexOf("\n<color=yellow>"); if (num > 0) { text = text.Substring(0, num); } string localizedDaysWithPrefix = LocalizationManager.Instance.GetLocalizedDaysWithPrefix("recipe.required_prefix", recipeSO.requiredDays); ((TMP_Text)textRecipeOutput).text = text + "\n<color=yellow>" + localizedDaysWithPrefix + "</color>"; } } } [HarmonyPatch(typeof(UIManager))] [HarmonyPatch("OpenJournal")] public class UIManagerJournalPatch { private class FinancialData { public int salesIncome; public int rentCost; public int maintenanceCost; public int employeeCost; public int orderCost; public int otherCost; public int taxCost; } private static readonly FieldInfo dailyTransactionsField = AccessTools.Field(typeof(GameManager), "dailyTransactions"); [HarmonyPostfix] private static void OpenJournalPatch(UIManager __instance) { ConfigManager instance = ConfigManager.Instance; if (instance != null && !instance.IsPatchEnabled("UIManagerJournal")) { return; } try { GameObject panelJournal = __instance.panelJournal; if ((Object)(object)panelJournal == (Object)null) { return; } Transform val = panelJournal.transform.Find("Content/Row/Content"); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.Find("Stats"); if ((Object)(object)val2 == (Object)null) { return; } Transform val3 = val2.Find("Column"); if ((Object)(object)val3 == (Object)null) { return; } FinancialData financialData = CalculateFinancialData(); for (int i = 0; i < val3.childCount; i++) { Transform child = val3.GetChild(i); if (((Object)child).name.StartsWith("Financial_")) { Object.Destroy((Object)(object)((Component)child).gameObject); } } int num = -1; for (int j = 0; j < val3.childCount; j++) { if (((Object)val3.GetChild(j)).name == "Maintenance") { num = j; break; } } int salesIncome = financialData.salesIncome; int rentCost = financialData.rentCost; int maintenanceCost = financialData.maintenanceCost; int employeeCost = financialData.employeeCost; int orderCost = financialData.orderCost; int otherCost = financialData.otherCost; int num2 = Math.Abs(rentCost) + Math.Abs(maintenanceCost); if (employeeCost < 0) { num2 += Math.Abs(employeeCost); } int num3 = num2; if (orderCost < 0) { num3 += Math.Abs(orderCost); } if (otherCost < 0) { num3 += Math.Abs(otherCost); } int num4 = salesIncome - num3; int num5 = Math.Max(0, num4); int num6 = GameManager.Instance.initialTaxPercentage; EventSO currentEvent = GameManager.Instance.GetCurrentEvent(); if ((Object)(object)currentEvent != (Object)null) { num6 = Mathf.RoundToInt((float)num6 * currentEvent.taxMultiplier); } int num7 = Mathf.RoundToInt((float)num5 * ((float)num6 / 100f)); int num8 = num4 - num7; int num9 = num3 + num7; int siblingIndex = num + 1; CreateFinancialEntry(val3, siblingIndex++, "Financial_Sales", LocalizationManager.Instance.GetLocalizedText("financial.sales"), $"{salesIncome} C"); string arg = ((num7 > 0) ? "-" : ""); CreateFinancialEntry(val3, siblingIndex++, "Financial_Tax", LocalizationManager.Instance.GetLocalizedText("financial.tax"), $"{arg}{num7} C"); string arg2 = ((num8 >= 0) ? "+" : ""); CreateFinancialEntry(val3, siblingIndex++, "Financial_NetProfit", LocalizationManager.Instance.GetLocalizedText("financial.net_profit"), $"{arg2}{num8} C"); string arg3 = ((num9 > 0) ? "-" : ""); CreateFinancialEntry(val3, siblingIndex, "Financial_TotalExpenses", LocalizationManager.Instance.GetLocalizedText("financial.total_expenses"), $"{arg3}{num9} C"); } catch (Exception arg4) { Debug.LogError((object)$"[BetterMarketPlus] Error in UIManagerJournalPatch: {arg4}"); } } private static void CreateFinancialEntry(Transform parent, int siblingIndex, string name, string leftText, string rightText) { Transform val = parent.Find("Capacity"); if ((Object)(object)val == (Object)null) { return; } GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, parent); ((Object)obj).name = name; obj.transform.SetSiblingIndex(siblingIndex); Transform val2 = obj.transform.Find("Left"); Transform val3 = obj.transform.Find("Right"); if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null) { TextMeshProUGUI componentInChildren = ((Component)val2).GetComponentInChildren<TextMeshProUGUI>(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = leftText; } TextMeshProUGUI componentInChildren2 = ((Component)val3).GetComponentInChildren<TextMeshProUGUI>(); if ((Object)(object)componentInChildren2 != (Object)null) { ((TMP_Text)componentInChildren2).text = rightText; } } } private static FinancialData CalculateFinancialData() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected I4, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00f6: Unknown result type (might be due to invalid IL or missing references) FinancialData financialData = new FinancialData(); if (dailyTransactionsField.GetValue(GameManager.Instance) is List<Transaction> list) { foreach (Transaction item in list) { TransactionType transactionType = item.TransactionType; switch ((int)transactionType) { case 0: financialData.salesIncome += item.Amount; break; case 5: financialData.employeeCost += item.Amount; break; case 4: financialData.rentCost += item.Amount; break; case 3: financialData.maintenanceCost += item.Amount; break; case 1: financialData.orderCost += item.Amount; break; case 2: financialData.taxCost += item.Amount; break; case 6: financialData.otherCost += item.Amount; break; } } } int rent = GameManager.Instance.GetRent(); int maintenanceValue = GameManager.Instance.GetMaintenanceValue(); if (financialData.rentCost == 0) { financialData.rentCost = -rent; } if (financialData.maintenanceCost == 0) { financialData.maintenanceCost = -maintenanceValue; } return financialData; } } } namespace BetterMarketPlus.Localization { public static class LocalizationHelper { private static readonly string[] DefaultTranslationLanguages = new string[3] { "zh", "zh-Hant", "en" }; public static void InitializeLanguageFiles() { string text = Path.Combine(Paths.ConfigPath, "BetterMarketPlus", "Localization"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } string[] defaultTranslationLanguages = DefaultTranslationLanguages; foreach (string text2 in defaultTranslationLanguages) { string filePath = Path.Combine(text, text2 + ".json"); EnsureLanguageFile(text2, filePath); } } private static void EnsureLanguageFile(string language, string filePath) { Dictionary<string, string> defaultTranslations = GetDefaultTranslations(language); if (File.Exists(filePath)) { string text = File.ReadAllText(filePath); Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(text); bool flag = false; foreach (KeyValuePair<string, string> item in defaultTranslations) { if (!dictionary.ContainsKey(item.Key)) { dictionary[item.Key] = item.Value; flag = true; } } if (flag) { text = JsonConvert.SerializeObject((object)dictionary, (Formatting)1); File.WriteAllText(filePath, text); } } else { string contents = JsonConvert.SerializeObject((object)defaultTranslations, (Formatting)1); File.WriteAllText(filePath, contents); } } public static Dictionary<string, string> GetDefaultTranslations(string language) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); switch (language) { case "zh": dictionary.Add("financial.sales", "销售总额"); dictionary.Add("financial.tax", "应缴税费"); dictionary.Add("financial.current_tax_rate", "当前税率"); dictionary.Add("financial.net_profit", "净利润"); dictionary.Add("financial.total_expenses", "总支出"); dictionary.Add("plugin.initialized", "BetterMarketPlus 初始化成功!"); dictionary.Add("plugin.author_prefix", "作者:"); dictionary.Add("plugin.initializing", "BetterMarketPlus 开始初始化..."); dictionary.Add("plugin.runtime", "当前运行时: {0}"); dictionary.Add("plugin.unity_version", "Unity 版本: {0}"); dictionary.Add("plugin.harmony_version", "Harmony 版本: {0}"); dictionary.Add("plugin.unknown", "未知"); dictionary.Add("plugin.applying_patches", "正在应用 BetterMarketPlus..."); dictionary.Add("plugin.patches_applied", "BetterMarketPlus 已成功应用!"); dictionary.Add("plugin.patches_skipped", "补丁已应用,跳过..."); dictionary.Add("plugin.language_fallback", "不支持的语言 {0},使用英语作为备用。"); dictionary.Add("common.remaining_prefix", "剩余:"); dictionary.Add("common.day_single", "{0} 天"); dictionary.Add("common.day_plural", "{0} 天"); dictionary.Add("recipe.required_prefix", "需要:"); dictionary.Add("order.inventory", "库存:{0}"); dictionary.Add("beehive.trees", "周围树木:{0} 颗"); dictionary.Add("beehive.output", "预计产出:{0} 箱"); dictionary.Add("common.unknown_item", "未知物品"); dictionary.Add("compatibility.betterorder_enabled", "检测到 BetterOrder 模组已启用库存提示,已禁用本模组的库存提示。"); dictionary.Add("tree.stage.seedling", "幼苗期"); dictionary.Add("tree.stage.growing", "成长期"); dictionary.Add("tree.stage.adult", "成年期"); dictionary.Add("tree.stage.mature", "成熟期(可收获)"); dictionary.Add("tree.growth_info", "已成长 {0} - {1}"); dictionary.Add("tree.move_hint", "提示:使用 冲刺键+锄头 可无损移动(保留完整状态)"); dictionary.Add("tree.status.harvest_progress", "收获进度 {0}%"); dictionary.Add("tree.status.has_beehive", "有蜂巢"); dictionary.Add("patches.alcohol_machine", "启用酿酒机提示信息"); dictionary.Add("patches.animal", "启用动物提示信息"); dictionary.Add("patches.bee_hive", "启用蜂箱提示信息"); dictionary.Add("patches.bee_hive_radius", "启用蜂箱范围显示"); dictionary.Add("patches.cheese_machine", "启用奶酪机提示信息"); dictionary.Add("patches.dirt", "启用农田提示信息"); dictionary.Add("patches.sprinkler", "启用洒水器范围显示"); dictionary.Add("patches.tree", "启用树木提示信息"); dictionary.Add("patches.tree_move", "启用树木无损移动"); dictionary.Add("patches.dock_order_tile", "启用码头订单库存显示"); dictionary.Add("patches.free_placement", "启用装饰品自由放置"); dictionary.Add("patches.rotation_45", "启用物品45度旋转"); dictionary.Add("patches.coin_tooltip", "启用金币提示信息"); dictionary.Add("patches.journal", "启用日志界面提示信息"); dictionary.Add("patches.recipe", "启用配方界面提示信息"); dictionary.Add("patches.horse_cargo", "启用马匹负重提示信息"); dictionary.Add("horse.cargo_info", "负重: {0}/{1}"); dictionary.Add("horse.cargo_full", "(已满载)"); break; case "zh-Hant": dictionary.Add("financial.sales", "銷售總額"); dictionary.Add("financial.tax", "應繳稅費"); dictionary.Add("financial.current_tax_rate", "當前稅率"); dictionary.Add("financial.net_profit", "淨利潤"); dictionary.Add("financial.total_expenses", "總支出"); dictionary.Add("plugin.initialized", "BetterMarketPlus 初始化成功!"); dictionary.Add("plugin.author_prefix", "作者:"); dictionary.Add("plugin.initializing", "BetterMarketPlus 開始初始化..."); dictionary.Add("plugin.runtime", "當前運行時: {0}"); dictionary.Add("plugin.unity_version", "Unity 版本: {0}"); dictionary.Add("plugin.harmony_version", "Harmony 版本: {0}"); dictionary.Add("plugin.unknown", "未知"); dictionary.Add("plugin.applying_patches", "正在應用 BetterMarketPlus..."); dictionary.Add("plugin.patches_applied", "BetterMarketPlus 已成功應用!"); dictionary.Add("plugin.patches_skipped", "補丁已應用,跳過..."); dictionary.Add("plugin.language_fallback", "不支持的語言 {0},使用英語作為備用。"); dictionary.Add("common.remaining_prefix", "剩餘:"); dictionary.Add("common.day_single", "{0} 天"); dictionary.Add("common.day_plural", "{0} 天"); dictionary.Add("recipe.required_prefix", "需要:"); dictionary.Add("order.inventory", "庫存:{0}"); dictionary.Add("beehive.trees", "周圍樹木:{0} 顆"); dictionary.Add("beehive.output", "預計產出:{0} 箱"); dictionary.Add("common.unknown_item", "未知物品"); dictionary.Add("compatibility.betterorder_enabled", "檢測到 BetterOrder 模組已啟用庫存提示,已禁用本模組的庫存提示。"); dictionary.Add("tree.stage.seedling", "幼苗期"); dictionary.Add("tree.stage.growing", "成長期"); dictionary.Add("tree.stage.adult", "成年期"); dictionary.Add("tree.stage.mature", "成熟期(可收獲)"); dictionary.Add("tree.growth_info", "已成長 {0} - {1}"); dictionary.Add("tree.move_hint", "提示:使用 衝刺鍵+鋤頭 可無損移動(保留完整狀態)"); dictionary.Add("tree.status.harvest_progress", "收獲進度 {0}%"); dictionary.Add("tree.status.has_beehive", "有蜂巢"); dictionary.Add("patches.alcohol_machine", "啟用釀酒機提示信息"); dictionary.Add("patches.animal", "啟用動物提示信息"); dictionary.Add("patches.bee_hive", "啟用蜂箱提示信息"); dictionary.Add("patches.bee_hive_radius", "啟用蜂箱範圍顯示"); dictionary.Add("patches.cheese_machine", "啟用奶酪機提示信息"); dictionary.Add("patches.dirt", "啟用農田提示信息"); dictionary.Add("patches.sprinkler", "啟用洒水器範圍顯示"); dictionary.Add("patches.tree", "啟用樹木提示信息"); dictionary.Add("patches.tree_move", "啟用樹木無損移動"); dictionary.Add("patches.dock_order_tile", "啟用碼頭訂單庫存顯示"); dictionary.Add("patches.free_placement", "啟用裝飾品自由放置"); dictionary.Add("patches.rotation_45", "啟用物品45度旋轉"); dictionary.Add("patches.coin_tooltip", "啟用金幣提示信息"); dictionary.Add("patches.journal", "啟用日誌界面提示信息"); dictionary.Add("patches.recipe", "啟用配方界面提示信息"); dictionary.Add("patches.horse_cargo", "啟用馬匹負重提示信息"); dictionary.Add("horse.cargo_info", "負重: {0}/{1}"); dictionary.Add("horse.cargo_full", "(已滿載)"); break; default: dictionary.Add("financial.sales", "Total Sales"); dictionary.Add("financial.tax", "Tax Payable"); dictionary.Add("financial.current_tax_rate", "Current Tax Rate"); dictionary.Add("financial.net_profit", "Net Profit"); dictionary.Add("financial.total_expenses", "Total Expenses"); dictionary.Add("plugin.initialized", "BetterMarketPlus initialized successfully!"); dictionary.Add("plugin.author_prefix", "Author: "); dictionary.Add("plugin.initializing", "BetterMarketPlus initializing..."); dictionary.Add("plugin.runtime", "Current Runtime: {0}"); dictionary.Add("plugin.unity_version", "Unity Version: {0}"); dictionary.Add("plugin.harmony_version", "Harmony Version: {0}"); dictionary.Add("plugin.unknown", "Unknown"); dictionary.Add("plugin.applying_patches", "Applying BetterMarketPlus patches..."); dictionary.Add("plugin.patches_applied", "BetterMarketPlus patches applied successfully!"); dictionary.Add("plugin.patches_skipped", "Patches already applied, skipping..."); dictionary.Add("plugin.language_fallback", "Unsupported language {0}, using English as fallback."); dictionary.Add("common.remaining_prefix", "Remaining: "); dictionary.Add("common.day_single", "1 day"); dictionary.Add("common.day_plural", "{0} days"); dictionary.Add("recipe.required_prefix", "Required: "); dictionary.Add("order.inventory", "Stock: {0}"); dictionary.Add("beehive.trees", "Trees: {0}"); dictionary.Add("beehive.output", "Est. Output: {0} boxes"); dictionary.Add("common.unknown_item", "Unknown Item"); dictionary.Add("compatibility.betterorder_enabled", "Detected that the BetterOrder mod has enabled inventory prompts, this mod's inventory prompts have been disabled."); dictionary.Add("tree.stage.seedling", "Seedling"); dictionary.Add("tree.stage.growing", "Growing"); dictionary.Add("tree.stage.adult", "Adult"); dictionary.Add("tree.stage.mature", "Mature (Harvestable)"); dictionary.Add("tree.growth_info", "Grown {0} - {1}"); dictionary.Add("tree.move_hint", "Tip: Use Sprint Key + Hoe to move losslessly (preserves full state)"); dictionary.Add("tree.status.harvest_progress", "Harvest Progress {0}%"); dictionary.Add("tree.status.has_beehive", "Has Beehive"); dictionary.Add("patches.alcohol_machine", "Enable brewing machine tooltip information"); dictionary.Add("patches.animal", "Enable animal tooltip information"); dictionary.Add("patches.bee_hive", "Enable beehive tooltip information"); dictionary.Add("patches.bee_hive_radius", "Enable beehive range display"); dictionary.Add("patches.cheese_machine", "Enable cheese machine tooltip information"); dictionary.Add("patches.dirt", "Enable farmland tooltip information"); dictionary.Add("patches.sprinkler", "Enable sprinkler range display"); dictionary.Add("patches.tree", "Enable tree tooltip information"); dictionary.Add("patches.tree_move", "Enable lossless tree moving"); dictionary.Add("patches.dock_order_tile", "Enable dock order inventory display"); dictionary.Add("patches.free_placement", "Enable free placement of decorative items"); dictionary.Add("patches.rotation_45", "Enable 45-degree item rotation"); dictionary.Add("patches.coin_tooltip", "Enable coin tooltip information"); dictionary.Add("patches.journal", "Enable journal interface tooltip information"); dictionary.Add("patches.recipe", "Enable recipe interface tooltip information"); dictionary.Add("patches.horse_cargo"