Decompiled source of MassReplant v1.0.1

MassReplant.dll

Decompiled 5 days ago
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace MassReplant;

[BepInPlugin("MassReplant", "MassReplant", "1.0.0")]
public class MassReplantPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Pickable), "Interact")]
	private static class Pickable_Interact_Patch
	{
		private static void Prefix(Pickable __instance, Humanoid character, bool ___m_picked, bool ___m_enabled, ZNetView ___m_nview, out bool __state)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			__state = cfgEnabled.Value && !___m_picked && ___m_enabled && (Object)(object)___m_nview != (Object)null && ___m_nview.IsValid() && (Object)(object)character != (Object)null && (Object)(object)character == (Object)(object)Player.m_localPlayer && !Input.GetKey(skipKey.Value);
		}

		private static void Postfix(Pickable __instance, bool __state)
		{
			//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_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!__state)
			{
				return;
			}
			if (plantByCrop == null)
			{
				BuildPlantMap();
			}
			if (plantByCrop.TryGetValue(PrefabName(((Component)__instance).gameObject), out var value))
			{
				Vector3 position = ((Component)__instance).transform.position;
				Quaternion rotation = ((Component)__instance).transform.rotation;
				if (scheduled.Add(Key(position)))
				{
					((MonoBehaviour)instance).StartCoroutine(Replant(__instance, value, position, rotation));
				}
			}
		}
	}

	public const string Guid = "MassReplant";

	private static MassReplantPlugin instance;

	private static ConfigEntry<bool> cfgEnabled;

	private static ConfigEntry<KeyCode> skipKey;

	private static ConfigEntry<float> firstDelay;

	private static ConfigEntry<float> giveUpAfter;

	private static ConfigEntry<bool> debug;

	private static Dictionary<string, Piece> plantByCrop;

	private static readonly HashSet<long> scheduled = new HashSet<long>();

	private void Awake()
	{
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		instance = this;
		cfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replant a crop with seeds from your inventory right after you pick it.");
		skipKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "SkipKey", (KeyCode)308, "Hold this key while picking to harvest without replanting.");
		firstDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ReplantDelay", 0.35f, "Seconds to wait after picking before replanting.");
		giveUpAfter = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WaitForSeeds", 4f, "If you have no seeds yet, keep trying this many seconds (the crop's own seeds drop and get picked up).");
		debug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug", false, "Log every replant.");
		new Harmony("MassReplant").PatchAll(typeof(MassReplantPlugin).Assembly);
	}

	private static void Dbg(string s)
	{
		if (debug.Value)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo((object)s);
		}
	}

	private static string PrefabName(GameObject go)
	{
		string name = ((Object)go).name;
		int num = name.IndexOf("(Clone)");
		if (num < 0)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	private static void BuildPlantMap()
	{
		plantByCrop = new Dictionary<string, Piece>();
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		foreach (GameObject item in (List<GameObject>)AccessTools.Field(typeof(ZNetScene), "m_prefabs").GetValue(ZNetScene.instance))
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			Plant component = item.GetComponent<Plant>();
			Piece component2 = item.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || component.m_grownPrefabs == null)
			{
				continue;
			}
			GameObject[] grownPrefabs = component.m_grownPrefabs;
			foreach (GameObject val in grownPrefabs)
			{
				if ((Object)(object)val != (Object)null && !plantByCrop.ContainsKey(((Object)val).name))
				{
					plantByCrop[((Object)val).name] = component2;
				}
			}
		}
		((BaseUnityPlugin)instance).Logger.LogInfo((object)("Known replantable crops: " + plantByCrop.Count));
	}

	private static long Key(Vector3 p)
	{
		//IL_0000: 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)
		return ((long)Mathf.RoundToInt(p.x * 20f) << 32) ^ Mathf.RoundToInt(p.z * 20f);
	}

	private unsafe static IEnumerator Replant(Pickable crop, Piece piece, Vector3 pos, Quaternion rot)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		long key = Key(pos);
		float start = Time.time;
		yield return (object)new WaitForSeconds(firstDelay.Value);
		try
		{
			while (true)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Object)(object)crop != (Object)null && !crop.GetPicked()))
				{
					break;
				}
				Heightmap val = Heightmap.FindHeightmap(pos);
				if ((Object)(object)val == (Object)null || !val.IsCultivated(pos) || !PrivateArea.CheckAccess(pos, 0f, false, false))
				{
					break;
				}
				bool flag = (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey());
				if (flag || localPlayer.HaveRequirements(piece, (RequirementMode)0))
				{
					localPlayer.PlacePiece(piece, pos, rot, false, false);
					if (!flag)
					{
						localPlayer.ConsumeResources(piece.m_resources, 0, -1, 1);
					}
					string name = ((Object)piece).name;
					Vector3 val2 = pos;
					Dbg("Replanted " + name + " at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString());
					break;
				}
				if (Time.time - start > giveUpAfter.Value)
				{
					break;
				}
				yield return (object)new WaitForSeconds(0.4f);
			}
		}
		finally
		{
			scheduled.Remove(key);
		}
	}
}