Decompiled source of PavedRoadAnywhere v0.1.2

plugins\PavedRoadAnywhere\PavedRoadAnywhere.dll

Decompiled 6 days ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyDescription("Removes only the Stonecutter requirement from Valheim's Paved Road hoe action")]
[assembly: AssemblyCompany("Daishi11")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyTitle("PavedRoadAnywhere")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyProduct("PavedRoadAnywhere")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyVersion("0.1.2.0")]
namespace Daishi11.PavedRoadAnywhere;

[BepInPlugin("daishi11.valheim.pavedroadanywhere", "Paved Road Anywhere", "0.1.2")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player), "SetPlaceMode", new Type[] { typeof(PieceTable) })]
	private static class PlayerSetPlaceModePatch
	{
		private static void Prefix(PieceTable __0)
		{
			RefreshPavedRoadStation(__0);
		}
	}

	[HarmonyPatch(typeof(ZNetScene), "OnDestroy")]
	private static class ZNetSceneOnDestroyPatch
	{
		private static void Prefix()
		{
			RestoreOriginalStation();
		}
	}

	public const string PluginGuid = "daishi11.valheim.pavedroadanywhere";

	public const string PluginName = "Paved Road Anywhere";

	public const string PluginVersion = "0.1.2";

	private Harmony harmony;

	private static ManualLogSource log;

	private static Piece ownedPiece;

	private static CraftingStation originalStation;

	private static bool loggedSuccess;

	private static bool loggedConflict;

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		log = ((BaseUnityPlugin)this).Logger;
		harmony = new Harmony("daishi11.valheim.pavedroadanywhere");
		harmony.PatchAll(typeof(Plugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Paved Road Anywhere active. Only the Paved Road crafting-station requirement will be removed. Discovery runs only when entering a build mode; no HaveRequirements hot-path patch is used.");
	}

	private void OnDestroy()
	{
		RestoreOriginalStation();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private static void RefreshPavedRoadStation(PieceTable table)
	{
		if ((Object)(object)table == (Object)null || table.m_pieces == null)
		{
			return;
		}
		if ((Object)(object)ownedPiece != (Object)null)
		{
			if ((Object)(object)ownedPiece.m_craftingStation == (Object)null)
			{
				return;
			}
			if ((Object)(object)ownedPiece.m_craftingStation == (Object)(object)originalStation)
			{
				ownedPiece.m_craftingStation = null;
				return;
			}
			if (!loggedConflict)
			{
				loggedConflict = true;
				log.LogWarning((object)"Paved Road station was changed by another mod while Paved Road Anywhere was active. The conflicting value was left untouched.");
			}
			ClearOwnership();
		}
		string candidateName;
		Piece val = FindPavedRoad(table, out candidateName);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)val.m_craftingStation == (Object)null)
		{
			if (!loggedSuccess)
			{
				loggedSuccess = true;
				log.LogInfo((object)("Paved Road prefab '" + candidateName + "' already has no crafting-station requirement."));
			}
			return;
		}
		ownedPiece = val;
		originalStation = val.m_craftingStation;
		val.m_craftingStation = null;
		if (!loggedSuccess)
		{
			loggedSuccess = true;
			log.LogInfo((object)("Paved Road prefab '" + candidateName + "' found; its crafting-station requirement was removed. Stone cost and normal placement rules remain unchanged."));
		}
	}

	private static Piece FindPavedRoad(PieceTable table, out string candidateName)
	{
		candidateName = null;
		for (int i = 0; i < table.m_pieces.Count; i++)
		{
			GameObject val = table.m_pieces[i];
			if (!((Object)(object)val == (Object)null) && IsVanillaPavedRoadName(((Object)val).name))
			{
				Piece component = val.GetComponent<Piece>();
				if (!((Object)(object)component == (Object)null))
				{
					candidateName = ((Object)val).name;
					return component;
				}
			}
		}
		Piece result = null;
		string text = null;
		int num = 0;
		for (int j = 0; j < table.m_pieces.Count; j++)
		{
			GameObject val2 = table.m_pieces[j];
			if (IsSemanticPavedRoadCandidate(val2))
			{
				result = val2.GetComponent<Piece>();
				text = ((Object)val2).name;
				num++;
				if (num > 1)
				{
					return null;
				}
			}
		}
		if (num == 1)
		{
			candidateName = text;
			return result;
		}
		return null;
	}

	private static bool IsVanillaPavedRoadName(string name)
	{
		if (!string.Equals(name, "paved_road_v2", StringComparison.Ordinal) && !string.Equals(name, "paved_road_v2(Clone)", StringComparison.Ordinal) && !string.Equals(name, "paved_road", StringComparison.Ordinal))
		{
			return string.Equals(name, "paved_road(Clone)", StringComparison.Ordinal);
		}
		return true;
	}

	private static bool IsSemanticPavedRoadCandidate(GameObject root)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Invalid comparison between Unknown and I4
		if ((Object)(object)root == (Object)null)
		{
			return false;
		}
		Piece component = root.GetComponent<Piece>();
		if ((Object)(object)component == (Object)null || (Object)(object)component.m_craftingStation == (Object)null)
		{
			return false;
		}
		TerrainModifier[] componentsInChildren = root.GetComponentsInChildren<TerrainModifier>(true);
		int num = 0;
		if (componentsInChildren != null)
		{
			foreach (TerrainModifier val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (int)val.m_paintType == 2)
				{
					num++;
				}
			}
		}
		if (num != 1)
		{
			return false;
		}
		Requirement[] resources = component.m_resources;
		if (resources == null || resources.Length != 1)
		{
			return false;
		}
		Requirement val2 = resources[0];
		if (val2 == null || val2.m_amount != 1 || (Object)(object)val2.m_resItem == (Object)null || (Object)(object)((Component)val2.m_resItem).gameObject == (Object)null)
		{
			return false;
		}
		string name = ((Object)((Component)val2.m_resItem).gameObject).name;
		if (!string.Equals(name, "Stone", StringComparison.Ordinal))
		{
			return string.Equals(name, "Stone(Clone)", StringComparison.Ordinal);
		}
		return true;
	}

	private static void RestoreOriginalStation()
	{
		if ((Object)(object)ownedPiece == (Object)null)
		{
			ClearOwnership();
			return;
		}
		if ((Object)(object)ownedPiece.m_craftingStation == (Object)null)
		{
			ownedPiece.m_craftingStation = originalStation;
		}
		else if ((Object)(object)ownedPiece.m_craftingStation != (Object)(object)originalStation && !loggedConflict)
		{
			loggedConflict = true;
			if (log != null)
			{
				log.LogWarning((object)"Paved Road station changed before cleanup; the conflicting value was left untouched.");
			}
		}
		ClearOwnership();
	}

	private static void ClearOwnership()
	{
		ownedPiece = null;
		originalStation = null;
	}
}