Decompiled source of FarmingPlantEasilyFix v1.0.0

FarmingPlantEasilyFix.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("FarmingPlantEasilyFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FarmingPlantEasilyFix")]
[assembly: AssemblyTitle("FarmingPlantEasilyFix")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FarmingPlantEasilyFix;

internal static class ClientPatch
{
	private static bool bulkPlanting;

	private static FieldInfo ignoreBiomeLevelField;

	public static void Apply(Harmony harmony)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Expected O, but got Unknown
		//IL_00b5: Expected O, but got Unknown
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("Advize_PlantEasily.PlacementController");
		MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "PlacePiece", (Type[])null, (Type[])null));
		if (methodInfo == null)
		{
			Plugin.Log.LogWarning((object)"Could not find Advize_PlantEasily.PlacementController.PlacePiece, client-side hook skipped. PlantEasily version mismatch?");
			return;
		}
		Type type2 = AccessTools.TypeByName("Farming.Farming");
		ignoreBiomeLevelField = ((type2 == null) ? null : AccessTools.Field(type2, "ignoreBiomeLevel"));
		if (ignoreBiomeLevelField == null)
		{
			Plugin.Log.LogWarning((object)"Could not read Farming's Ignore Biome Level setting; biome override will not be applied to bulk-planted crops.");
		}
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ClientPatch), "PlacePiecePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ClientPatch), "PlacePieceFinalizer", (Type[])null), (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Plant), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ClientPatch), "PlantAwakePostfix", (Type[])null)
		{
			priority = 600
		}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		Plugin.Log.LogInfo((object)"Client-side PlantEasily hook installed.");
	}

	private static void PlacePiecePrefix()
	{
		bulkPlanting = true;
	}

	private static void PlacePieceFinalizer()
	{
		bulkPlanting = false;
	}

	private static void PlantAwakePostfix(Plant __instance)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		if (!bulkPlanting)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component == (Object)null) ? null : component.GetZDO());
		if (!((Object)(object)localPlayer == (Object)null) && val != null && !(val.GetFloat(Plugin.SkillKeyHash, 0f) > 0f))
		{
			float num = ((Character)localPlayer).GetSkillFactor((SkillType)106) + 1E-14f;
			val.Set(Plugin.SkillKeyHash, num);
			int ignoreBiomeLevel = GetIgnoreBiomeLevel();
			if (ignoreBiomeLevel > 0 && num >= (float)ignoreBiomeLevel / 100f)
			{
				__instance.m_biome = (Biome)(-1);
			}
		}
	}

	private static int GetIgnoreBiomeLevel()
	{
		if (ignoreBiomeLevelField == null)
		{
			return 0;
		}
		if (!(ignoreBiomeLevelField.GetValue(null) is ConfigEntry<int> val))
		{
			return 0;
		}
		return val.Value;
	}
}
[BepInPlugin("nin.valheim.farmingplanteasilyfix", "FarmingPlantEasilyFix", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "nin.valheim.farmingplanteasilyfix";

	public const string NAME = "FarmingPlantEasilyFix";

	public const string VERSION = "1.0.0";

	internal const string FarmingGuid = "org.bepinex.plugins.farming";

	internal const string PlantEasilyGuid = "advize.PlantEasily";

	internal const string SkillKey = "Farming Skill Level";

	internal static readonly int SkillKeyHash = StringExtensionMethods.GetStableHashCode("Farming Skill Level");

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Harmony harmony = new Harmony("nin.valheim.farmingplanteasilyfix");
		ServerPatch.Apply(harmony);
		if (Chainloader.PluginInfos.ContainsKey("advize.PlantEasily"))
		{
			ClientPatch.Apply(harmony);
		}
		else
		{
			Log.LogInfo((object)"PlantEasily not loaded, client-side hook skipped (server-side ZDO fix still active).");
		}
	}
}
internal static class ServerPatch
{
	private struct LastFactor
	{
		public float factor;

		public float time;
	}

	private struct PendingPlant
	{
		public ZDOID id;

		public long creator;

		public float time;
	}

	private const float CacheWindowSeconds = 120f;

	private const float PendingWindowSeconds = 20f;

	private const uint RevisionBump = 4u;

	private static bool receiving;

	private static readonly List<ZDOID> newIds = new List<ZDOID>();

	private static readonly Dictionary<long, LastFactor> lastFactorByCreator = new Dictionary<long, LastFactor>();

	private static readonly List<PendingPlant> pending = new List<PendingPlant>();

	private static readonly Dictionary<int, bool> plantPrefabCache = new Dictionary<int, bool>();

	public static void Apply(Harmony harmony)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		//IL_00af: 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_00d1: Expected O, but got Unknown
		//IL_00d1: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(ZDOMan), "CreateNewZDO", new Type[3]
		{
			typeof(ZDOID),
			typeof(Vector3),
			typeof(int)
		}, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(ZDOMan), "RPC_ZDOData", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null)
		{
			Plugin.Log.LogError((object)"Could not find ZDOMan.CreateNewZDO / ZDOMan.RPC_ZDOData, server-side fix disabled. Game update?");
			return;
		}
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ServerPatch), "CreateNewZdoPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(ServerPatch), "RpcZdoDataPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ServerPatch), "RpcZdoDataFinalizer", (Type[])null), (HarmonyMethod)null);
		Plugin.Log.LogInfo((object)"Server-side ZDO fix installed.");
	}

	private static bool IsServer()
	{
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			return ZNet.instance.IsServer();
		}
		return false;
	}

	private static void RpcZdoDataPrefix()
	{
		receiving = IsServer();
	}

	private static void CreateNewZdoPostfix(ZDO __result)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		if (receiving && __result != null)
		{
			newIds.Add(__result.m_uid);
		}
	}

	private static void RpcZdoDataFinalizer()
	{
		if (!receiving)
		{
			return;
		}
		receiving = false;
		try
		{
			Process();
		}
		finally
		{
			newIds.Clear();
		}
	}

	private static void Process()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		float time = Time.time;
		ZDOMan instance = ZDOMan.instance;
		if (instance == null)
		{
			return;
		}
		foreach (ZDOID newId in newIds)
		{
			ZDO zDO = instance.GetZDO(newId);
			if (zDO != null && IsPlant(zDO.GetPrefab()))
			{
				long num = zDO.GetLong(ZDOVars.s_creator, 0L);
				float num2 = zDO.GetFloat(Plugin.SkillKeyHash, 0f);
				if (num != 0L && num2 > 0f)
				{
					lastFactorByCreator[num] = new LastFactor
					{
						factor = num2,
						time = time
					};
				}
			}
		}
		foreach (ZDOID newId2 in newIds)
		{
			ZDO zDO2 = instance.GetZDO(newId2);
			if (zDO2 != null && IsPlant(zDO2.GetPrefab()))
			{
				long num3 = zDO2.GetLong(ZDOVars.s_creator, 0L);
				if (num3 != 0L && !(zDO2.GetFloat(Plugin.SkillKeyHash, 0f) > 0f) && !TryStamp(zDO2, num3, time))
				{
					pending.Add(new PendingPlant
					{
						id = newId2,
						creator = num3,
						time = time
					});
				}
			}
		}
		for (int num4 = pending.Count - 1; num4 >= 0; num4--)
		{
			PendingPlant pendingPlant = pending[num4];
			ZDO zDO3 = instance.GetZDO(pendingPlant.id);
			if (zDO3 == null || time - pendingPlant.time > 20f || TryStamp(zDO3, pendingPlant.creator, time))
			{
				pending.RemoveAt(num4);
			}
		}
	}

	private static bool TryStamp(ZDO zdo, long creator, float now)
	{
		if (zdo.GetFloat(Plugin.SkillKeyHash, 0f) > 0f)
		{
			return true;
		}
		if (!lastFactorByCreator.TryGetValue(creator, out var value) || now - value.time > 120f)
		{
			return false;
		}
		zdo.Set(Plugin.SkillKeyHash, value.factor);
		zdo.DataRevision += 4;
		return true;
	}

	private static bool IsPlant(int prefabHash)
	{
		if (plantPrefabCache.TryGetValue(prefabHash, out var value))
		{
			return value;
		}
		ZNetScene instance = ZNetScene.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return false;
		}
		GameObject prefab = instance.GetPrefab(prefabHash);
		value = (Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<Plant>() != (Object)null;
		plantPrefabCache[prefabHash] = value;
		return value;
	}
}