Decompiled source of FurnitureAnywhere v0.0.1

FurnitureAnywhere/FurnitureAnywhere.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FurnitureAnywhere")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FurnitureAnywhere")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0fec61d2-f919-4d6a-850f-04a49f1dbdab")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FurnitureAnywhere
{
	[BepInPlugin("chemified.FurnitureAnywhere", "FurnitureAnywhere", "0.0.1")]
	internal class FurnitureAnywhere : BaseUnityPlugin
	{
		private const string modGUID = "chemified.FurnitureAnywhere";

		private const string modName = "FurnitureAnywhere";

		private const string modVersion = "0.0.1";

		private readonly Harmony harmony = new Harmony("chemified.FurnitureAnywhere");

		public static FurnitureAnywhere Instance { get; private set; }

		internal static ManualLogSource mls { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("chemified.FurnitureAnywhere");
			FurnitureAnywhereConfig.InitializeConfig();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			IEnumerable<Type> enumerable = from t in executingAssembly.GetTypes()
				where t.Namespace == "FurnitureAnywhere.Patches" && t.IsClass && t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Any()
				select t;
			foreach (Type item in enumerable)
			{
				try
				{
					mls.LogInfo((object)("Patching " + item.Name + "..."));
					harmony.PatchAll(item);
				}
				catch (Exception ex)
				{
					mls.LogError((object)("Failed to patch " + item.Name + ": " + ex.Message));
				}
			}
		}

		public void BindConfig<T>(ref ConfigEntry<T> config, string section, string key, T defaultValue, string description = "")
		{
			config = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description);
		}
	}
	internal class FurnitureAnywhereConfig
	{
		internal static ConfigEntry<bool> configToggleHelpersOutside;

		internal static ConfigEntry<bool> configToggleHelperOptimize;

		internal static void InitializeConfig()
		{
			FurnitureAnywhere.Instance.BindConfig(ref configToggleHelpersOutside, "Toggles", "Enable Helpers Outside", defaultValue: false, "Allows helpers to navigate outside the tavern. Disabled by default due to the performance impact.\nHelpers will still complete their task even if they cannot reach the station outside, they just won't walk there physically.");
			FurnitureAnywhere.Instance.BindConfig(ref configToggleHelperOptimize, "Toggles", "Enable Helpers Optimization", defaultValue: true, "Enables a small optimization that should reduce frame drops when helpers are idle, especially when \"Enable Helpers Outside\" is enabled.\nThis should generally be left enabled with \"Enable Helpers Outside\" on.");
		}
	}
}
namespace FurnitureAnywhere.Patches
{
	[HarmonyPatch(typeof(SurfaceSnapFurnitureTool), "Start")]
	internal class FurniturePatch
	{
		[HarmonyPostfix]
		private static void ApplyTerrainToLayerMask(SurfaceSnapFurnitureTool __instance)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo fieldInfo = AccessTools.Field(typeof(SurfaceSnapFurnitureTool), "_groundProjection");
			if ((bool)fieldInfo.GetValue(__instance))
			{
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(SurfaceSnapFurnitureTool), "_surfaceLM");
				LayerMask val = (LayerMask)fieldInfo2.GetValue(__instance);
				int num = LayerMask.NameToLayer("Terrain");
				if (num != -1)
				{
					((LayerMask)(ref val)).value = ((LayerMask)(ref val)).value | (1 << num);
					fieldInfo2.SetValue(__instance, val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(HelpersManager), "GetReachablePointOnNavMesh")]
	internal class HelperNavigationPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			if (!FurnitureAnywhereConfig.configToggleHelpersOutside.Value)
			{
				FurnitureAnywhere.mls.LogInfo((object)(MethodBase.GetCurrentMethod()?.DeclaringType?.Name + " disabled, skipping"));
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeMatcher val = new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"TavernMainRoom", (string)null)
			});
			if (val.IsInvalid)
			{
				FurnitureAnywhere.mls.LogInfo((object)"Could not find TavernMainRoom, skipping patch");
				return list;
			}
			val.SearchBack((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Ldc_I4_1));
			if (val.IsInvalid)
			{
				FurnitureAnywhere.mls.LogInfo((object)"Could not find Ldc_I4_1, skipping patch");
				return list;
			}
			if (val.Pos + 6 > list.Count)
			{
				FurnitureAnywhere.mls.LogInfo((object)"Instructions out of range, skipping patch");
				return list;
			}
			val.RemoveInstructions(6);
			val.Insert((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldc_I4_M1, (object)null)
			});
			return val.Instructions();
		}
	}
	[HarmonyPatch(typeof(HelpersManager), "GiveCleanerTask")]
	internal class GiveTaskOptimization
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (!FurnitureAnywhereConfig.configToggleHelperOptimize.Value)
			{
				FurnitureAnywhere.mls.LogInfo((object)(MethodBase.GetCurrentMethod()?.DeclaringType?.Name + " disabled, skipping..."));
				return instructions;
			}
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			CodeMatcher val = new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).Start();
			MethodInfo targetMethod = AccessTools.Method(typeof(HelpersManager), "GetReachablePointOnNavMesh", (Type[])null, (Type[])null);
			int num = 0;
			int num2 = 3;
			while (val.IsValid && num < num2)
			{
				if (!val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Call && instr.operand is MethodInfo methodInfo && methodInfo.Equals(targetMethod))).IsValid)
				{
					FurnitureAnywhere.mls.LogInfo((object)"No more GetReachablePointOnNavMesh calls found");
					break;
				}
				int pos = val.Pos;
				try
				{
					int pos2 = val.SearchBack((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Ldarg_0)).Pos;
					int pos3 = val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Brfalse || instr.opcode == OpCodes.Brfalse_S)).Pos;
					int pos4 = val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Ldarg_0)).Pos;
					int pos5 = val.SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Brtrue || instr.opcode == OpCodes.Brtrue_S)).Pos;
					List<CodeInstruction> range = list.GetRange(pos2, pos3 - pos2 + 1);
					List<CodeInstruction> range2 = list.GetRange(pos4, pos5 - pos4 + 1);
					IEnumerable<CodeInstruction> collection = range2.Concat(range);
					list.RemoveRange(pos2, pos5 - pos2 + 1);
					list.InsertRange(pos2, collection);
					num++;
				}
				catch (Exception ex)
				{
					FurnitureAnywhere.mls.LogError((object)$"Error flipping match at position {pos}: {ex.Message}");
					break;
				}
			}
			if (num < num2)
			{
				FurnitureAnywhere.mls.LogWarning((object)$"Found {num} matches instead of expected {num2}");
			}
			return list;
		}
	}
}