Decompiled source of CS Hammer Tweak v1.0.0

plugins/CSHammerTweak.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CastleStructures.HammerCompat
{
	[BepInPlugin("codex.CastleStructures.HammerCompat", "CastleStructures Hammer Compat", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <RetryInjectionRoutine>d__14 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

			private int <i>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RetryInjectionRoutine>d__14(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Expected O, but got Unknown
				int num = <>1__state;
				Plugin plugin = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__2++;
					break;
				}
				if (<i>5__2 < 60)
				{
					if (plugin.TryInjectPieces("Retry"))
					{
						return false;
					}
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				if (!plugin._sawCastlePieces)
				{
					((BaseUnityPlugin)plugin).Logger.LogWarning((object)"Timed out waiting for CastleStructures pieces (rkc_*) to appear. Original CastleStructures may not be loaded.");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "codex.CastleStructures.HammerCompat";

		public const string PluginName = "CastleStructures Hammer Compat";

		public const string PluginVersion = "1.0.0";

		private const string CastlePrefix = "rkc_";

		private const string CastleCategory = "Castle";

		private const string BuildItTable = "_RKCustomTable";

		private ConfigEntry<bool> _showInVanillaHammer;

		private ConfigEntry<bool> _showInImprovedHammer;

		private bool _vanillaInjected;

		private bool _improvedInjected;

		private bool _sawCastlePieces;

		private void Awake()
		{
			_showInVanillaHammer = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowInVanillaHammer", true, "If true, inject CastleStructures pieces into vanilla Hammer. Requires restart to apply.");
			_showInImprovedHammer = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowInImprovedHammer", true, "If true and BuildIt is installed, inject CastleStructures pieces into BuildIt's Improved Hammer (_RKCustomTable). Requires restart to apply.");
			((BaseUnityPlugin)this).Config.Save();
			if (!_showInVanillaHammer.Value && !_showInImprovedHammer.Value)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Both CastleStructures hammer compat toggles are disabled. Nothing will be injected.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"CastleStructures Hammer Compat loaded. Config changes require restart (not applied live).");
			PrefabManager.OnPrefabsRegistered += TryInjectFromEvent;
			((MonoBehaviour)this).StartCoroutine(RetryInjectionRoutine());
		}

		private void OnDestroy()
		{
			PrefabManager.OnPrefabsRegistered -= TryInjectFromEvent;
		}

		private void TryInjectFromEvent()
		{
			TryInjectPieces("OnPrefabsRegistered");
		}

		[IteratorStateMachine(typeof(<RetryInjectionRoutine>d__14))]
		private IEnumerator RetryInjectionRoutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RetryInjectionRoutine>d__14(0)
			{
				<>4__this = this
			};
		}

		private bool TryInjectPieces(string source)
		{
			List<GameObject> list = FindCastlePieces();
			if (list.Count == 0)
			{
				return false;
			}
			_sawCastlePieces = true;
			bool flag = !_showInVanillaHammer.Value;
			bool flag2 = !_showInImprovedHammer.Value;
			if (_showInVanillaHammer.Value)
			{
				EnsureCategory("Hammer", "Castle");
				PieceTable val = ResolvePieceTable("Hammer");
				if ((Object)(object)val != (Object)null)
				{
					int num = InjectIntoTable("Hammer", val, list, "Castle", ((BaseUnityPlugin)this).Logger);
					if (num > 0 || _vanillaInjected)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"[{source}] CastleStructures -> Hammer injected {num} new pieces.");
					}
					_vanillaInjected = true;
					flag = true;
				}
			}
			if (_showInImprovedHammer.Value)
			{
				PieceTable val2 = ResolvePieceTable("_RKCustomTable");
				if ((Object)(object)val2 != (Object)null)
				{
					EnsureCategory("_RKCustomTable", "Castle");
					int num2 = InjectIntoTable("_RKCustomTable", val2, list, "Castle", ((BaseUnityPlugin)this).Logger);
					if (num2 > 0 || _improvedInjected)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] CastleStructures -> {1} injected {2} new pieces.", source, "_RKCustomTable", num2));
					}
					_improvedInjected = true;
					flag2 = true;
				}
				else if (IsBuildItLoaded())
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[" + source + "] BuildIt detected but _RKCustomTable not available yet. Will retry."));
				}
			}
			if (flag && flag2)
			{
				PrefabManager.OnPrefabsRegistered -= TryInjectFromEvent;
				return true;
			}
			return false;
		}

		private List<GameObject> FindCastlePieces()
		{
			List<GameObject> list = new List<GameObject>();
			if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null)
			{
				return list;
			}
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null) && (((Object)prefab).name ?? string.Empty).StartsWith("rkc_", StringComparison.OrdinalIgnoreCase) && !((Object)(object)prefab.GetComponent<Piece>() == (Object)null))
				{
					list.Add(prefab);
				}
			}
			return list;
		}

		private static int InjectIntoTable(string tableName, PieceTable table, List<GameObject> prefabs, string categoryName, ManualLogSource logger)
		{
			if (table.m_pieces == null)
			{
				table.m_pieces = new List<GameObject>();
			}
			int num = 0;
			PieceManager instance = PieceManager.Instance;
			MethodInfo[] array = ((instance != null) ? (from m in ((object)instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public)
				where m.Name == "RegisterPieceInPieceTable"
				select m).ToArray() : Array.Empty<MethodInfo>());
			foreach (GameObject prefab in prefabs)
			{
				if (!table.m_pieces.Any((GameObject p) => (Object)(object)p != (Object)null && string.Equals(((Object)p).name, ((Object)prefab).name, StringComparison.Ordinal)))
				{
					bool flag = false;
					if (instance != null && array.Length != 0)
					{
						flag = TryRegisterViaPieceManager(instance, array, tableName, table, prefab, categoryName);
					}
					if (!flag)
					{
						table.m_pieces.Add(prefab);
						logger.LogDebug((object)("Fallback injected piece '" + ((Object)prefab).name + "' into '" + tableName + "' by direct table list add."));
					}
					num++;
				}
			}
			return num;
		}

		private static bool TryRegisterViaPieceManager(object pieceManager, MethodInfo[] registerMethods, string tableName, PieceTable table, GameObject prefab, string categoryName)
		{
			foreach (MethodInfo methodInfo in registerMethods)
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				bool flag = true;
				for (int j = 0; j < parameters.Length; j++)
				{
					Type parameterType = parameters[j].ParameterType;
					string text = parameters[j].Name ?? string.Empty;
					if (parameterType == typeof(string))
					{
						if (text.IndexOf("table", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							array[j] = tableName;
						}
						else if (text.IndexOf("piece", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("prefab", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							array[j] = ((Object)prefab).name;
						}
						else if (text.IndexOf("categor", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							array[j] = categoryName;
						}
						else
						{
							array[j] = categoryName;
						}
					}
					else if (typeof(GameObject).IsAssignableFrom(parameterType))
					{
						array[j] = prefab;
					}
					else if (typeof(PieceTable).IsAssignableFrom(parameterType))
					{
						array[j] = table;
					}
					else
					{
						if (!(parameterType == typeof(bool)))
						{
							flag = false;
							break;
						}
						array[j] = false;
					}
				}
				if (flag)
				{
					try
					{
						methodInfo.Invoke(pieceManager, array);
						return true;
					}
					catch
					{
					}
				}
			}
			return false;
		}

		private PieceTable ResolvePieceTable(string tableName)
		{
			try
			{
				if (tableName == "Hammer")
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab("Hammer");
					return (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_buildPieces;
				}
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(tableName);
				return ((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<PieceTable>() : null;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to resolve piece table '" + tableName + "': " + ex.Message));
				return null;
			}
		}

		private void EnsureCategory(string tableName, string categoryName)
		{
			try
			{
				object instance = PieceManager.Instance;
				if (instance == null)
				{
					return;
				}
				MethodInfo[] source = (from m in instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public)
					where m.Name == "AddPieceCategory"
					select m).ToArray();
				MethodInfo methodInfo = source.FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters3 = m.GetParameters();
					return parameters3.Length == 2 && parameters3[0].ParameterType == typeof(string) && parameters3[1].ParameterType == typeof(string);
				});
				if (methodInfo != null)
				{
					methodInfo.Invoke(instance, new object[2] { tableName, categoryName });
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered piece category '" + categoryName + "' for table '" + tableName + "' via AddPieceCategory(string,string)."));
					return;
				}
				PieceTable val = ResolvePieceTable(tableName);
				if ((Object)(object)val != (Object)null)
				{
					MethodInfo methodInfo2 = source.FirstOrDefault(delegate(MethodInfo m)
					{
						ParameterInfo[] parameters2 = m.GetParameters();
						return parameters2.Length == 2 && typeof(PieceTable).IsAssignableFrom(parameters2[0].ParameterType) && parameters2[1].ParameterType == typeof(string);
					});
					if (methodInfo2 != null)
					{
						methodInfo2.Invoke(instance, new object[2] { val, categoryName });
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered piece category '" + categoryName + "' for table '" + tableName + "' via AddPieceCategory(PieceTable,string)."));
						return;
					}
				}
				MethodInfo methodInfo3 = source.FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					return parameters.Length == 1 && parameters[0].ParameterType == typeof(string);
				});
				if (methodInfo3 != null)
				{
					methodInfo3.Invoke(instance, new object[1] { categoryName });
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered global piece category '" + categoryName + "' (table-specific overload unavailable for '" + tableName + "')."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("No supported AddPieceCategory overload found while adding '" + categoryName + "' to '" + tableName + "'."));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to add category '" + categoryName + "' to '" + tableName + "': " + ex.Message));
			}
		}

		private static bool IsBuildItLoaded()
		{
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if ((pluginInfo.Key ?? string.Empty).IndexOf("buildit", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				PluginInfo value = pluginInfo.Value;
				if (((value != null) ? value.Metadata : null) != null)
				{
					string obj = pluginInfo.Value.Metadata.GUID ?? string.Empty;
					string text = pluginInfo.Value.Metadata.Name ?? string.Empty;
					if (obj.IndexOf("buildit", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("buildit", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
}