Decompiled source of Stitched Items v1.0.0

StitchedItems.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using DM;
using FhpSLib;
using HarmonyLib;
using Landfall.TABS;
using SI;
using SIComponents;
using SLMA;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("StitchedItems")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("GeeztJeez")]
[assembly: AssemblyProduct("StitchedItems")]
[assembly: AssemblyCopyright("Copyright © 4Ever")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7acfaef0-7669-4401-8bff-5a9a02e18c75")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace SI
{
	public static class Manager
	{
		public static string comment;

		public static void Init(LandfallContentDatabase db)
		{
			UTI.LoadBundle("stitchitemsbundle");
			Sprite val = UTI.LoadTexture2Sprite("icon_items");
			string categoryName = "Stitched Items";
			GameObject val2 = UTI.LoadGmObj("EmptyPropItem");
			int startId = 99999999;
			comment = "----------------------------------------------------------------------------------------------------------------------------";
			comment = "Custom Clothes";
			comment = "----------------------------------------------------------------------------------------------------------------------------";
			UTI.ICat.SetTag(UPool.MyPool.AddObject("SmartSkinnedPropScale", val2, true, (HideFlags)52, val, UTI.IDScan(UTI.assetType.Ability, startId), true), categoryName, (TagType)0);
			UTI.ICat.SetTag(UPool.MyPool.AddObject("SmartSkinnedPropRotation", val2, true, (HideFlags)52, val, UTI.IDScan(UTI.assetType.Ability, startId), true), categoryName, (TagType)0);
			UTI.ICat.SetTag(UPool.MyPool.AddObject("SmartSkinnedPropPosition", val2, true, (HideFlags)52, val, UTI.IDScan(UTI.assetType.Ability, startId), true), categoryName, (TagType)0);
		}

		public static void SetItemObject(GameObject itemObject)
		{
			if ((Object)(object)itemObject == (Object)(object)UPool.MyPool.GetObject("SmartSkinnedPropScale"))
			{
				itemObject.AddComponent<SmartSkinnedPropBehaviour>().smartType = SmartSkinnedPropBehaviour.SmartType.Scale;
			}
			if ((Object)(object)itemObject == (Object)(object)UPool.MyPool.GetObject("SmartSkinnedPropRotation"))
			{
				itemObject.AddComponent<SmartSkinnedPropBehaviour>().smartType = SmartSkinnedPropBehaviour.SmartType.Rotation;
			}
			if ((Object)(object)itemObject == (Object)(object)UPool.MyPool.GetObject("SmartSkinnedPropPosition"))
			{
				itemObject.AddComponent<SmartSkinnedPropBehaviour>().smartType = SmartSkinnedPropBehaviour.SmartType.Position;
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("GeeztJeez.StitchedItems", "StitchedItems", "1.0.0")]
	internal class Loader : BaseUnityPlugin
	{
		public static string modName;

		public static bool DebugEnabled;

		public static string modtitle;

		private void ApplyHarmony()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new Harmony(modName).PatchAll(Assembly.GetExecutingAssembly());
				Log(" Harmony patched successfully!");
			}
			catch (Exception ex)
			{
				LogError("Harmony patch failed: " + ex);
				Log("Please contact Geezt Jeez or try reloading the game for proper installation...");
			}
		}

		static Loader()
		{
			DebugEnabled = false;
			modtitle = "Stitched Items";
			modName = "StitchedItems";
		}

		public static void Log(string message)
		{
			if (DebugEnabled)
			{
				Debug.Log((object)$"[{modName}] {message}");
			}
		}

		public static void LogWarning(string message)
		{
			if (DebugEnabled)
			{
				Debug.LogWarning((object)$"[{modName}] {message}");
			}
		}

		public static void LogError(string message)
		{
			if (DebugEnabled)
			{
				Debug.LogError((object)$"[{modName}] {message}");
			}
		}

		private void Awake()
		{
			ApplyHarmony();
			((MonoBehaviour)this).StartCoroutine(Call());
		}

		private IEnumerator Call()
		{
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)Object.FindObjectOfType<ServiceLocator>() != (Object)null));
			yield return (object)new WaitUntil((Func<bool>)(() => ServiceLocator.GetService<ISaveLoaderService>() != null));
			Log($"Loading {modtitle}!");
			SLMALoader.GetInstance();
			Manager.Init(ContentDatabase.Instance().LandfallContentDatabase);
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			for (int num = 0; num < array.Length; num++)
			{
				Manager.SetItemObject(array[num]);
			}
			Log($"Loaded {modtitle} Successfully!");
		}
	}
	public static class UTI
	{
		public static class ICat
		{
			public static void SetTag(GameObject item, string categoryName = "Technical Items", TagType tagType = (TagType)0)
			{
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if ((Object)(object)item == (Object)null)
					{
						Loader.LogWarning("[SetTag] Provided item is null.");
						return;
					}
					CharacterItem componentInChildren = item.GetComponentInChildren<CharacterItem>();
					if ((Object)(object)componentInChildren == (Object)null)
					{
						Loader.LogWarning("[SetTag] CharacterItem not found in children.");
						return;
					}
					if (componentInChildren.tags == null)
					{
						componentInChildren.tags = new List<Tag>();
					}
					string uniqueValue = categoryName;
					int num = 0;
					while (componentInChildren.tags.Exists((Tag tag) => tag.value == uniqueValue))
					{
						num++;
						uniqueValue = $"{categoryName}_{num}";
						if (num > 999999)
						{
							Loader.LogError("[SetTag] Failed to generate a unique tag value after 999999 attempts.");
							return;
						}
					}
					componentInChildren.tags.Add(new Tag
					{
						tagType = tagType,
						value = uniqueValue
					});
				}
				catch (Exception ex)
				{
					Loader.LogError("[SetTag] Exception occurred: " + ex.Message);
				}
			}
		}

		public enum assetType
		{
			Prop,
			Ability
		}

		public static string comment;

		public static AssetBundle bundle;

		private static Dictionary<DatabaseID, GameObject> CombatMoves
		{
			get
			{
				Dictionary<DatabaseID, GameObject> dictionary = HelpLibrary.m_combatMoves;
				if (dictionary == null)
				{
					dictionary = (HelpLibrary.m_combatMoves = new Dictionary<DatabaseID, GameObject>());
				}
				return dictionary;
			}
		}

		private static Dictionary<DatabaseID, GameObject> CharacterProps
		{
			get
			{
				Dictionary<DatabaseID, GameObject> dictionary = HelpLibrary.m_characterProps;
				if (dictionary == null)
				{
					dictionary = (HelpLibrary.m_characterProps = new Dictionary<DatabaseID, GameObject>());
				}
				return dictionary;
			}
		}

		public static void LoadBundle(string assetBundleName)
		{
			Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(assetBundleName);
			if (manifestResourceStream == null)
			{
				Loader.LogError("[LoadBundle] Failed to find resource: " + assetBundleName);
			}
			else if (!manifestResourceStream.CanRead)
			{
				Loader.LogError("[LoadBundle] Resource stream is not readable: " + assetBundleName);
			}
			else
			{
				bundle = AssetBundle.LoadFromStream(manifestResourceStream);
			}
		}

		public static Sprite LoadTexture2Sprite(string name)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = (Texture2D)bundle.LoadAsset(name);
			((Texture)val).filterMode = (FilterMode)0;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		public static GameObject LoadGmObj(string name)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (GameObject)bundle.LoadAsset(name);
		}

		private static bool IsOccupied(DatabaseID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!CombatMoves.ContainsKey(id))
			{
				return CharacterProps.ContainsKey(id);
			}
			return true;
		}

		public static int IDScan(assetType type, int startId = 1)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			int num = Math.Max(1, startId);
			DatabaseID id = default(DatabaseID);
			((DatabaseID)(ref id))..ctor(num);
			while (IsOccupied(id))
			{
				Loader.LogWarning($"[IDChecker] ID {num} in use, trying {num + 1}…");
				num++;
				((DatabaseID)(ref id))..ctor(num);
			}
			Loader.Log($"[IDChecker] Found free ID: {num}");
			return num;
		}
	}
}
namespace SIComponents
{
	public class StitchedClothingBehaviour : MonoBehaviour
	{
		public Transform UnitBone;

		public string BoneName;

		public List<Transform> ClothingBones = new List<Transform>();
	}
}
namespace TIHarmonyPatches
{
	[HarmonyPatch(typeof(Stitcher), "StitchUnitEditor")]
	internal static class StitcherHarmonyPatch
	{
		private static readonly Dictionary<Transform, Transform> ClothMasters;

		private static bool Prefix(GameObject sourceClothing, GameObject targetAvatar, TransformCatalog boneCatalog, ref GameObject[] __result)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			sourceClothing.SetActive(true);
			SkinnedMeshRenderer[] componentsInChildren = sourceClothing.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			__result = (GameObject[])(object)new GameObject[componentsInChildren.Length];
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				SkinnedMeshRenderer val = componentsInChildren[i];
				Transform[] bones = val.bones;
				foreach (Transform val2 in bones)
				{
					if (!((Object)(object)val2 == (Object)null) && ((Dictionary<string, Transform>)(object)boneCatalog).TryGetValue(((Object)val2).name, out Transform value))
					{
						Transform orCreateMaster = GetOrCreateMaster(value);
						Transform orCreatePropContainer = GetOrCreatePropContainer(orCreateMaster, sourceClothing);
						if ((Object)(object)val2.parent != (Object)(object)orCreatePropContainer)
						{
							val2.SetParent(orCreatePropContainer, true);
						}
						StitchedClothingBehaviour component = ((Component)orCreateMaster).GetComponent<StitchedClothingBehaviour>();
						if (!component.ClothingBones.Contains(val2))
						{
							component.ClothingBones.Add(val2);
						}
						val2.localPosition = Vector3.zero;
						val2.localRotation = Quaternion.identity;
						val2.localScale = Vector3.one;
					}
				}
				if ((Object)(object)val.rootBone != (Object)null && ((Dictionary<string, Transform>)(object)boneCatalog).TryGetValue(((Object)val.rootBone).name, out Transform value2))
				{
					Transform orCreatePropContainer2 = GetOrCreatePropContainer(GetOrCreateMaster(value2), sourceClothing);
					if ((Object)(object)val.rootBone.parent != (Object)(object)orCreatePropContainer2)
					{
						val.rootBone.SetParent(orCreatePropContainer2, true);
					}
				}
				__result[i] = ((Component)val).gameObject;
			}
			sourceClothing.transform.SetParent(targetAvatar.transform, false);
			return false;
		}

		private static Transform GetOrCreateMaster(Transform unitBone)
		{
			//IL_0021: 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_0036: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			if (ClothMasters.TryGetValue(unitBone, out var value))
			{
				return value;
			}
			GameObject val = new GameObject(((Object)unitBone).name + "ClothMaster");
			value = val.transform;
			value.SetParent(unitBone, false);
			value.localPosition = Vector3.zero;
			value.localRotation = Quaternion.identity;
			value.localScale = Vector3.one;
			StitchedClothingBehaviour stitchedClothingBehaviour = val.AddComponent<StitchedClothingBehaviour>();
			stitchedClothingBehaviour.UnitBone = unitBone;
			stitchedClothingBehaviour.BoneName = ((Object)unitBone).name;
			ClothMasters.Add(unitBone, value);
			return value;
		}

		static StitcherHarmonyPatch()
		{
			ClothMasters = new Dictionary<Transform, Transform>();
		}

		private static Transform GetOrCreatePropContainer(Transform clothMaster, GameObject sourceClothing)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			string text = ((Object)sourceClothing).name + "_" + ((Object)sourceClothing).GetInstanceID();
			Transform val = clothMaster.Find(text);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = new GameObject(text).transform;
			val.SetParent(clothMaster, false);
			val.localPosition = Vector3.zero;
			val.localRotation = Quaternion.identity;
			val.localScale = Vector3.one;
			return val;
		}
	}
	[HarmonyPatch(typeof(CharacterItem), "Equip", new Type[]
	{
		typeof(GameObject),
		typeof(PropItemData),
		typeof(TransformCatalog),
		typeof(Team),
		typeof(bool)
	})]
	public static class CharacterItemEquipHarmonyPatch
	{
		private static readonly FieldInfo GameObjectsField = AccessTools.Field(typeof(CharacterItem), "m_gameObjects");

		private static bool Prefix(CharacterItem __instance, GameObject unitRoot, PropItemData propData, TransformCatalog catalog, Team team, bool isUnitEditor, ref GameObject[] __result)
		{
			unitRoot.GetComponent<UnitRig>();
			if ((Object)(object)((Component)__instance).GetComponentInChildren<SkinnedMeshRenderer>() != (Object)null)
			{
				__instance.Equip();
				GameObject[] array = Stitcher.StitchUnitEditor(((Component)__instance).gameObject, unitRoot, catalog);
				GameObjectsField.SetValue(__instance, array);
				__result = array;
				return true;
			}
			return true;
		}
	}
}
namespace SIComponents
{
	public class SmartSkinnedPropBehaviour : MonoBehaviour
	{
		public enum SmartType
		{
			Scale,
			Position,
			Rotation
		}

		public int propBoneId;

		public int stitcherId;

		public SmartType smartType;

		public Vector3 values;

		public GameObject objectToAffect;

		private IEnumerator Start()
		{
			SetSettings();
			objectToAffect = ((Component)((Component)((Component)this).transform.root).GetComponentsInChildren<StitchedClothingBehaviour>()[stitcherId].ClothingBones.ToArray()[propBoneId]).gameObject;
			while ((Object)(object)objectToAffect == (Object)null)
			{
				Loader.Log("Fetching object...");
				yield return null;
			}
			if (Object.op_Implicit((Object)(object)objectToAffect))
			{
				if (smartType == SmartType.Scale)
				{
					objectToAffect.transform.localScale = values;
				}
				else if (smartType == SmartType.Position)
				{
					objectToAffect.transform.localPosition = values;
				}
				else
				{
					objectToAffect.transform.localRotation = Quaternion.Euler(values);
				}
			}
			((MonoBehaviour)this).StartCoroutine(MonitorPosition());
		}

		private void SetSettings()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localScale = ((Component)this).transform.localScale;
			stitcherId = Mathf.RoundToInt(localScale.x);
			propBoneId = Mathf.RoundToInt(localScale.y);
			values = ((Component)this).transform.localPosition;
		}

		private IEnumerator MonitorPosition()
		{
			((Component)this).transform.hasChanged = false;
			while (true)
			{
				if (((Component)this).transform.hasChanged)
				{
					((Component)this).transform.hasChanged = false;
					if (values != ((Component)this).transform.localPosition)
					{
						values = ((Component)this).transform.localPosition;
						if (Object.op_Implicit((Object)(object)objectToAffect))
						{
							switch (smartType)
							{
							case SmartType.Scale:
								objectToAffect.transform.localScale = values;
								break;
							case SmartType.Position:
								objectToAffect.transform.localPosition = values;
								break;
							case SmartType.Rotation:
								objectToAffect.transform.localRotation = Quaternion.Euler(values);
								break;
							}
						}
					}
				}
				yield return (object)new WaitForSeconds(0.1f);
			}
		}
	}
}