Decompiled source of SkinCopy v1.0.2

SkinCopy.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SkinCopy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SkinCopy")]
[assembly: AssemblyTitle("SkinCopy")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SkinCopy
{
	[BepInPlugin("purtzel_hd.skincopy", "SkinCopy", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyCode> Taste;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Taste = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "Window Key", (KeyCode)284, "Key to open/close the window");
			GameObject val = new GameObject("SkinCopy");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<Fenster>();
			Log.LogInfo((object)$"SkinCopy loaded. Window key: {Taste.Value}");
		}
	}
	internal static class Skin
	{
		public class Spieler
		{
			public Component Avatar;

			public string Name;

			public string SteamId;
		}

		private const BindingFlags All = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private const BindingFlags AllStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool _ready;

		private static FieldInfo _gdInstance;

		private static FieldInfo _gdPlayerList;

		private static FieldInfo _paCosmetics;

		private static FieldInfo _paName;

		private static FieldInfo _paSteamId;

		private static FieldInfo _paLocal;

		private static FieldInfo _pcRaw;

		private static FieldInfo _pcColors;

		private static FieldInfo _mmInstance;

		private static FieldInfo _mmEquipped;

		private static FieldInfo _mmUnlocks;

		private static FieldInfo _mmColors;

		private static FieldInfo _mmAssets;

		private static MethodInfo _mmUpdateLocal;

		private static MethodInfo _mmSave;

		private static List<int> _backupTeile;

		private static int[] _backupFarben;

		public static bool HatBackup => _backupTeile != null;

		public static void Init()
		{
			if (!_ready)
			{
				_ready = true;
				Type type = AccessTools.TypeByName("GameDirector");
				_gdInstance = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				_gdPlayerList = type.GetField("PlayerList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Type type2 = AccessTools.TypeByName("PlayerAvatar");
				_paCosmetics = type2.GetField("playerCosmetics", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_paName = type2.GetField("playerName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_paSteamId = type2.GetField("steamID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_paLocal = type2.GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Type type3 = AccessTools.TypeByName("PlayerCosmetics");
				_pcRaw = type3.GetField("cosmeticEquippedRaw", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_pcColors = type3.GetField("colorsEquipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Type type4 = AccessTools.TypeByName("MetaManager");
				_mmInstance = type4.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				_mmEquipped = type4.GetField("cosmeticEquipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_mmUnlocks = type4.GetField("cosmeticUnlocks", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_mmColors = type4.GetField("colorsEquipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_mmAssets = type4.GetField("cosmeticAssets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_mmUpdateLocal = AccessTools.Method(type4, "CosmeticPlayerUpdateLocal", (Type[])null, (Type[])null);
				_mmSave = AccessTools.Method(type4, "Save", (Type[])null, (Type[])null);
			}
		}

		public static List<Spieler> Andere()
		{
			Init();
			List<Spieler> list = new List<Spieler>();
			object obj = _gdInstance?.GetValue(null);
			if (obj == null || !(_gdPlayerList.GetValue(obj) is IList list2))
			{
				return list;
			}
			bool flag = default(bool);
			foreach (object item in list2)
			{
				Component val = (Component)((item is Component) ? item : null);
				if (!((Object)(object)val == (Object)null))
				{
					object value = _paLocal.GetValue(val);
					int num;
					if (value is bool)
					{
						flag = (bool)value;
						num = 1;
					}
					else
					{
						num = 0;
					}
					if (((uint)num & (flag ? 1u : 0u)) == 0)
					{
						list.Add(new Spieler
						{
							Avatar = val,
							Name = ((_paName.GetValue(val) as string) ?? "?"),
							SteamId = ((_paSteamId.GetValue(val) as string) ?? "?")
						});
					}
				}
			}
			return list;
		}

		public static string Kopieren(Spieler s)
		{
			Init();
			object obj = _mmInstance?.GetValue(null);
			if (obj == null)
			{
				return "Error: cosmetic system not found.";
			}
			object? value = _paCosmetics.GetValue(s.Avatar);
			Component val = (Component)((value is Component) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return s.Name + " has not loaded a skin yet.";
			}
			List<int> list = _pcRaw.GetValue(val) as List<int>;
			int[] array = _pcColors.GetValue(val) as int[];
			if (list == null)
			{
				return s.Name + " has not loaded a skin yet.";
			}
			List<int> list2 = _mmEquipped.GetValue(obj) as List<int>;
			List<int> freigeschaltet = _mmUnlocks.GetValue(obj) as List<int>;
			IList assets = _mmAssets.GetValue(obj) as IList;
			int[] array2 = _mmColors.GetValue(obj) as int[];
			if (list2 == null || freigeschaltet == null)
			{
				return "Error: could not read cosmetic data.";
			}
			if (_backupTeile == null)
			{
				_backupTeile = new List<int>(list2);
				_backupFarben = array2?.ToArray();
			}
			List<int> uebernehmen = list.Where((int id) => id >= 0 && assets != null && id < assets.Count && freigeschaltet.Contains(id)).Distinct().ToList();
			int num = list.Count((int id) => !uebernehmen.Contains(id));
			list2.Clear();
			list2.AddRange(uebernehmen);
			if (array != null && array2 != null)
			{
				Array.Copy(array, array2, Math.Min(array.Length, array2.Length));
			}
			Anwenden(obj);
			Plugin.Log.LogInfo((object)$"Copied skin from {s.Name} ({s.SteamId}): {uebernehmen.Count} items, {num} skipped.");
			if (num != 0)
			{
				return $"Copied skin from {s.Name} ({uebernehmen.Count} items). {num} item(s) skipped because you have not unlocked them.";
			}
			return $"Copied skin from {s.Name} ({uebernehmen.Count} items).";
		}

		public static string Zuruecksetzen()
		{
			Init();
			object obj = _mmInstance?.GetValue(null);
			if (obj == null || _backupTeile == null)
			{
				return "Nothing to restore.";
			}
			List<int> obj2 = _mmEquipped.GetValue(obj) as List<int>;
			int[] array = _mmColors.GetValue(obj) as int[];
			obj2?.Clear();
			obj2?.AddRange(_backupTeile);
			if (_backupFarben != null && array != null)
			{
				Array.Copy(_backupFarben, array, Math.Min(_backupFarben.Length, array.Length));
			}
			Anwenden(obj);
			_backupTeile = null;
			_backupFarben = null;
			return "Your own skin has been restored.";
		}

		private static void Anwenden(object meta)
		{
			try
			{
				_mmUpdateLocal?.Invoke(meta, new object[2] { true, true });
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Applying skin failed: {arg}");
			}
			try
			{
				_mmSave?.Invoke(meta, null);
			}
			catch (Exception arg2)
			{
				Plugin.Log.LogError((object)$"Saving failed: {arg2}");
			}
		}
	}
	internal class Fenster : MonoBehaviour
	{
		private const float WinW = 560f;

		private const float WinH = 900f;

		private const float ListH = 760f;

		private bool _open;

		private bool _toggleQueued;

		private bool _keyHeld;

		private Rect _rect;

		private Vector2 _scroll;

		private string _status = "";

		private List<Skin.Spieler> _spieler = new List<Skin.Spieler>();

		private Skin.Spieler _kopierenQueued;

		private bool _zurueckQueued;

		private bool _cursorLookupDone;

		private FieldInfo _cursorInstance;

		private MethodInfo _cursorUnlock;

		private GUIStyle _windowStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _nameStyle;

		private GUIStyle _smallStyle;

		private void Update()
		{
			if (_open)
			{
				CursorFrei();
			}
		}

		private void LateUpdate()
		{
			if (_open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void CursorFrei()
		{
			if (!_cursorLookupDone)
			{
				_cursorLookupDone = true;
				Type type = AccessTools.TypeByName("CursorManager");
				_cursorInstance = type?.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				_cursorUnlock = type?.GetMethod("Unlock", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			try
			{
				object obj = _cursorInstance?.GetValue(null);
				if (obj != null)
				{
					_cursorUnlock?.Invoke(obj, new object[1] { 0.1f });
				}
			}
			catch
			{
			}
		}

		private void OnGUI()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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)
			Event current = Event.current;
			if ((int)current.type == 4 && current.keyCode == Plugin.Taste.Value)
			{
				if (!_keyHeld)
				{
					_toggleQueued = true;
					_keyHeld = true;
				}
				current.Use();
			}
			else if ((int)current.type == 5 && current.keyCode == Plugin.Taste.Value)
			{
				_keyHeld = false;
			}
			if ((int)current.type == 8)
			{
				if (_toggleQueued)
				{
					_open = !_open;
					_toggleQueued = false;
					_status = "";
				}
				if (_kopierenQueued != null)
				{
					try
					{
						_status = Skin.Kopieren(_kopierenQueued);
					}
					catch (Exception ex)
					{
						_status = "Error while copying.";
						Plugin.Log.LogError((object)ex);
					}
					_kopierenQueued = null;
				}
				if (_zurueckQueued)
				{
					try
					{
						_status = Skin.Zuruecksetzen();
					}
					catch (Exception ex2)
					{
						_status = "Error while restoring.";
						Plugin.Log.LogError((object)ex2);
					}
					_zurueckQueued = false;
				}
				if (_open)
				{
					try
					{
						_spieler = Skin.Andere();
					}
					catch (Exception ex3)
					{
						_spieler = new List<Skin.Spieler>();
						Plugin.Log.LogError((object)ex3);
					}
				}
			}
			if (_open)
			{
				Styles();
				float num = Mathf.Clamp((float)Screen.height / 1080f, 1f, 3f);
				GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
				float num2 = (float)Screen.width / num;
				float num3 = (float)Screen.height / num;
				if (((Rect)(ref _rect)).width < 1f)
				{
					_rect = new Rect((num2 - 560f) / 2f, (num3 - 900f) / 2f, 560f, 900f);
				}
				_rect = GUI.Window(733101, _rect, new WindowFunction(Zeichnen), "SkinCopy", _windowStyle);
			}
		}

		private void Zeichnen(int id)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Space(6f);
			GUILayout.Label($"Players in lobby ({_spieler.Count})", _headerStyle, Array.Empty<GUILayoutOption>());
			_scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(760f) });
			if (_spieler.Count == 0)
			{
				GUILayout.Label("No other players found (only works inside a level).", _smallStyle, Array.Empty<GUILayoutOption>());
			}
			foreach (Skin.Spieler item in _spieler)
			{
				GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.Label(item.Name, _nameStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label(item.SteamId, _smallStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("Copy skin", (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(140f),
					GUILayout.Height(34f)
				}))
				{
					_kopierenQueued = item;
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			GUILayout.Label(_status ?? "", _smallStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.enabled = Skin.HatBackup;
			if (GUILayout.Button("Restore my skin", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(170f),
				GUILayout.Height(28f)
			}))
			{
				_zurueckQueued = true;
			}
			GUI.enabled = true;
			GUILayout.FlexibleSpace();
			GUILayout.Label($"{Plugin.Taste.Value} = close", _smallStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(100f),
				GUILayout.Height(28f)
			}))
			{
				_toggleQueued = true;
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
		}

		private void Styles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			if (_windowStyle == null)
			{
				_windowStyle = new GUIStyle(GUI.skin.window)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				Texture2D val = new Texture2D(1, 1)
				{
					hideFlags = (HideFlags)61
				};
				val.SetPixel(0, 0, new Color(0.08f, 0.08f, 0.1f, 0.96f));
				val.Apply();
				_windowStyle.normal.background = val;
				_windowStyle.onNormal.background = val;
				_headerStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 17,
					fontStyle = (FontStyle)1
				};
				_nameStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15
				};
				_smallStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					wordWrap = true
				};
				_smallStyle.normal.textColor = new Color(0.75f, 0.75f, 0.75f);
			}
		}
	}
}