Decompiled source of ValheimCreate v0.2.15

plugins\ValheimCreate\ValheimCreate.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ValheimCreate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.15.0")]
[assembly: AssemblyInformationalVersion("0.2.15+e8576d0c75f18f1a7da71fbbd0cd61e148f5fbb5")]
[assembly: AssemblyProduct("ValheimCreate")]
[assembly: AssemblyTitle("ValheimCreate")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.15.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimCreate
{
	internal static class FreePiecesConfig
	{
		internal sealed class ExtraPiece
		{
			internal string PrefabName { get; }

			internal string DisplayName { get; }

			internal ExtraPiece(string prefabName, string displayName)
			{
				PrefabName = prefabName;
				DisplayName = displayName;
			}
		}

		internal static readonly IReadOnlyList<ExtraPiece> All = new ExtraPiece[2]
		{
			new ExtraPiece("piece_groundtorch_wood", "Standing Wood Torch"),
			new ExtraPiece("stake_wall", "Stake Wall")
		};

		internal static readonly Dictionary<string, ConfigEntry<bool>> Entries = new Dictionary<string, ConfigEntry<bool>>();

		internal static void Bind(ConfigFile config)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			foreach (ExtraPiece item in All)
			{
				Entries[item.PrefabName] = config.Bind<bool>("Extra Free Pieces", item.DisplayName, false, new ConfigDescription("Place and remove " + item.DisplayName + " for free.", (AcceptableValueBase)null, Array.Empty<object>()));
			}
		}

		internal static bool IsEnabled(string prefabName)
		{
			if (Entries.TryGetValue(prefabName, out ConfigEntry<bool> value))
			{
				return value.Value;
			}
			return false;
		}
	}
	internal class FreePiecesUI : MonoBehaviour
	{
		private GameObject? _panel;

		private GameObject? _openButton;

		private bool _panelVisible;

		private void Start()
		{
			GUIManager.OnCustomGUIAvailable += CreateUI;
		}

		private void OnDestroy()
		{
			GUIManager.OnCustomGUIAvailable -= CreateUI;
		}

		private void Update()
		{
			if ((Object)(object)_openButton == (Object)null)
			{
				return;
			}
			bool flag = (Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).InPlaceMode() && (Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_pieceSelectionWindow != (Object)null && Hud.instance.m_pieceSelectionWindow.activeSelf;
			if (_openButton.activeSelf != flag)
			{
				_openButton.SetActive(flag);
				if (!flag)
				{
					SetPanelVisible(visible: false);
				}
			}
		}

		private void CreateUI()
		{
			CreateOpenButton();
			CreateConfigPanel();
		}

		private void CreateOpenButton()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			_openButton = GUIManager.Instance.CreateButton("Free Build Piece Selection", GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -290f), 130f, 34f);
			_openButton.SetActive(false);
			((UnityEvent)_openButton.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				SetPanelVisible(!_panelVisible);
			});
		}

		private void CreateConfigPanel()
		{
			//IL_0032: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_0135: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			float num = 110f + (float)FreePiecesConfig.All.Count * 44f;
			_panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 280f, num);
			GUIManager.Instance.CreateText("Extra Free Pieces", _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -28f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimOrange, true, Color.black, 240f, 36f, false);
			for (int i = 0; i < FreePiecesConfig.All.Count; i++)
			{
				FreePiecesConfig.ExtraPiece extraPiece = FreePiecesConfig.All[i];
				ConfigEntry<bool> val2 = FreePiecesConfig.Entries[extraPiece.PrefabName];
				float num2 = -72f - (float)i * 44f;
				GameObject obj = GUIManager.Instance.CreateToggle(_panel.transform, 36f, 36f);
				RectTransform component = obj.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(0f, 1f);
				component.anchoredPosition = new Vector2(36f, num2);
				Toggle component2 = obj.GetComponent<Toggle>();
				component2.isOn = val2.Value;
				Text componentInChildren = obj.GetComponentInChildren<Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = string.Empty;
				}
				GUIManager.Instance.CreateText(extraPiece.DisplayName, _panel.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(160f, num2), GUIManager.Instance.AveriaSerif, 16, Color.white, false, Color.black, 120f, 36f, false);
				ConfigEntry<bool> capturedEntry = val2;
				((UnityEvent<bool>)(object)component2.onValueChanged).AddListener((UnityAction<bool>)delegate(bool val)
				{
					capturedEntry.Value = val;
				});
			}
			((UnityEvent)GUIManager.Instance.CreateButton("Close", _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 28f), 100f, 34f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				SetPanelVisible(visible: false);
			});
			_panel.SetActive(false);
		}

		private void SetPanelVisible(bool visible)
		{
			_panelVisible = visible;
			GameObject? panel = _panel;
			if (panel != null)
			{
				panel.SetActive(visible);
			}
			GUIManager.BlockInput(visible);
		}
	}
	[BepInPlugin("dpshaef.ValheimCreate", "ValheimCreate", "0.2.15")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "dpshaef.ValheimCreate";

		public const string PluginName = "ValheimCreate";

		public const string PluginVersion = "0.2.15";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> FreeBuildEnabled;

		private readonly Harmony _harmony = new Harmony("dpshaef.ValheimCreate");

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			FreeBuildEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Free Build", "Enabled", true, new ConfigDescription("Remove resource costs for Building and Heavy Build pieces. All other categories (Misc, Crafting, Furniture) retain normal costs.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Order = 1
			} }));
			FreePiecesConfig.Bind(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.AddComponent<FreePiecesUI>();
			_harmony.PatchAll();
			Log.LogInfo((object)string.Format("{0} v{1} loaded. Free build: {2}", "ValheimCreate", "0.2.15", FreeBuildEnabled.Value));
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
		}
	}
}
namespace ValheimCreate.Patches
{
	internal static class FreeBuildPatch
	{
		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		private static class HaveRequirements_Patch
		{
			private static bool Prefix(Piece piece, RequirementMode mode, ref bool __result)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Invalid comparison between Unknown and I4
				if (!IsFreeCategory(piece) || (int)mode == 1)
				{
					return true;
				}
				__result = true;
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class UpdatePlacement_Patch
		{
			private static void Prefix(Player __instance)
			{
				PieceTable buildPieces = __instance.m_buildPieces;
				_suppressConsumption = IsFreeCategory((buildPieces != null) ? buildPieces.GetSelectedPiece() : null);
			}

			private static void Postfix()
			{
				_suppressConsumption = false;
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class ConsumeResources_Patch
		{
			private static bool Prefix()
			{
				Plugin.Log.LogInfo((object)$"[ConsumeResources] suppress={_suppressConsumption}");
				return !_suppressConsumption;
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class PlacePiece_Log_Patch
		{
			private static void Prefix(Player __instance, Piece piece, out int __state)
			{
				__state = ((Humanoid)__instance).GetInventory().CountItems("$item_wood", -1, true);
				Plugin.Log.LogInfo((object)string.Format("[PlacePiece] piece={0} isFree={1} suppress={2} m_noPlacementCost={3} wood_before={4}", ((piece != null) ? ((Object)piece).name : null) ?? "null", IsFreeCategory(piece), _suppressConsumption, __instance.m_noPlacementCost, __state));
			}

			private static void Postfix(Player __instance, int __state)
			{
				int num = ((Humanoid)__instance).GetInventory().CountItems("$item_wood", -1, true);
				Plugin.Log.LogInfo((object)$"[PlacePiece] wood_after={num}");
				if (num < __state)
				{
					Plugin.Log.LogError((object)$"[PlacePiece] WOOD DECREASED: {__state} -> {num}");
				}
			}
		}

		private static bool _suppressConsumption;

		internal static bool IsFreeCategory(Piece? piece)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			if ((Object)(object)piece == (Object)null || !Plugin.FreeBuildEnabled.Value)
			{
				return false;
			}
			if ((int)piece.m_category == 2 || (int)piece.m_category == 3)
			{
				return true;
			}
			return FreePiecesConfig.IsEnabled(Utils.GetPrefabName(((Component)piece).gameObject));
		}
	}
	internal static class FreeRemovePatch
	{
		[HarmonyPatch(typeof(Piece), "SetCreator")]
		private static class SetCreator_Patch
		{
			private static void Postfix(Piece __instance, long uid)
			{
				if (uid != 0L && Plugin.FreeBuildEnabled.Value && FreeBuildPatch.IsFreeCategory(__instance))
				{
					ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
					if ((Object)(object)component == (Object)null || !component.IsValid())
					{
						Plugin.Log.LogWarning((object)("[SetCreator] SKIPPED tagging " + ((Object)__instance).name + " — ZNetView null or invalid"));
						return;
					}
					component.GetZDO().Set(ZdoKeyHash, true);
					Plugin.Log.LogInfo((object)("[SetCreator] Tagged " + ((Object)__instance).name + " as free-build"));
				}
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		private static class DropResources_Patch
		{
			private static bool Prefix(Piece __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					return true;
				}
				return !component.GetZDO().GetBool(ZdoKeyHash, false);
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		private static class RemovePiece_Patch
		{
			private static void Prefix(Player __instance, out Piece? __state)
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				_savedStation = null;
				if (!Plugin.FreeBuildEnabled.Value)
				{
					return;
				}
				Camera val = (((Object)(object)GameCamera.instance != (Object)null) ? GameCamera.instance.m_camera : Camera.main);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[RemovePiece] No camera found");
					return;
				}
				int mask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" });
				RaycastHit val2 = default(RaycastHit);
				if (!Physics.Raycast(((Component)val).transform.position, ((Component)val).transform.forward, ref val2, __instance.m_maxPlaceDistance, mask))
				{
					return;
				}
				Piece componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					Plugin.Log.LogInfo((object)"[RemovePiece] Raycast hit but no Piece component found");
					return;
				}
				ManualLogSource log = Plugin.Log;
				string name = ((Object)componentInParent).name;
				object arg = componentInParent.m_category;
				CraftingStation craftingStation = componentInParent.m_craftingStation;
				log.LogInfo((object)string.Format("[RemovePiece] Aiming at {0} cat={1} station={2}", name, arg, ((craftingStation != null) ? ((Object)craftingStation).name : null) ?? "none"));
				if ((Object)(object)componentInParent.m_craftingStation == (Object)null)
				{
					Plugin.Log.LogInfo((object)"[RemovePiece] No crafting station required — no bypass needed");
					return;
				}
				if (!FreeBuildPatch.IsFreeCategory(componentInParent))
				{
					Plugin.Log.LogInfo((object)("[RemovePiece] " + ((Object)componentInParent).name + " is NOT a free category — skipping bypass"));
					return;
				}
				ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					Plugin.Log.LogWarning((object)("[RemovePiece] " + ((Object)componentInParent).name + " ZNetView null or invalid — cannot check tag"));
					return;
				}
				bool @bool = component.GetZDO().GetBool(ZdoKeyHash, false);
				Plugin.Log.LogInfo((object)$"[RemovePiece] {((Object)componentInParent).name} ZDO tag vc_freebuild={@bool}");
				if (@bool)
				{
					_savedStation = componentInParent.m_craftingStation;
					componentInParent.m_craftingStation = null;
					__state = componentInParent;
					Plugin.Log.LogInfo((object)("[RemovePiece] Bypassing station check for " + ((Object)componentInParent).name));
				}
			}

			private static void Postfix(Piece? __state)
			{
				if ((Object)(object)__state != (Object)null && (Object)(object)_savedStation != (Object)null)
				{
					__state.m_craftingStation = _savedStation;
					_savedStation = null;
				}
			}
		}

		private static readonly int ZdoKeyHash = StringExtensionMethods.GetStableHashCode("vc_freebuild");

		private static CraftingStation? _savedStation;
	}
}