Decompiled source of SWP Receiver v1.0.0

plugins/SWP_Receiver/SWP_Receiver.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SWP Team")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Lightweight receiver for SWP appearance sync - allows vanilla clients to see extended appearance values from mod users")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SWP_Receiver")]
[assembly: AssemblyTitle("SWP_Receiver")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SWPReceiver;

[BepInPlugin("com.swp.receiver", "SWP Receiver", "1.0.0")]
public class SWPReceiverPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlayerVisual), "Apply_NetworkedCharacterDisplay")]
	public static class Patch_PlayerVisual_ApplyNetworkedCharacterDisplay
	{
		private static bool Prepare()
		{
			return !_mainModPresent;
		}

		private static void Postfix(PlayerVisual __instance)
		{
			//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_007a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_mainModPresent && _initialized && !((Object)(object)__instance == (Object)null))
				{
					PlayerAppearanceStruct playerAppearanceStruct = __instance._playerAppearanceStruct;
					int instanceID = ((Object)__instance).GetInstanceID();
					int frameCount = Time.frameCount;
					if (!_lastAppliedFrame.TryGetValue(instanceID, out var value) || frameCount - value >= 5)
					{
						_lastAppliedFrame[instanceID] = frameCount;
						TryPurgeOldEntries(frameCount);
						ApplyExtendedValues(__instance, playerAppearanceStruct);
					}
				}
			}
			catch (Exception ex)
			{
				LogDebug("Patch Postfix error: " + ex.Message);
			}
		}
	}

	[HarmonyPatch(typeof(PlayerVisual), "OnAppearanceStructChange")]
	public static class Patch_PlayerVisual_OnAppearanceStructChange
	{
		private static int _lastRebuildFrame = -999999;

		private const int REBUILD_DEBOUNCE_FRAMES = 30;

		private static bool Prepare()
		{
			return !_mainModPresent;
		}

		private static void Postfix(PlayerVisual __instance, PlayerAppearanceStruct _old, PlayerAppearanceStruct _new)
		{
			//IL_0031: 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)
			try
			{
				if (_mainModPresent || !_initialized || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				string text = _old._setRaceTag ?? "";
				string text2 = _new._setRaceTag ?? "";
				if (string.IsNullOrEmpty(text2) || string.Equals(text, text2, StringComparison.OrdinalIgnoreCase))
				{
					return;
				}
				string raceName = "";
				try
				{
					if ((Object)(object)__instance._playerRaceModel != (Object)null && (Object)(object)__instance._playerRaceModel._scriptablePlayerRace != (Object)null)
					{
						raceName = __instance._playerRaceModel._scriptablePlayerRace._raceName ?? "";
					}
				}
				catch
				{
					raceName = "";
				}
				string text3 = NormalizeRaceName(text2);
				string b = NormalizeRaceName(raceName);
				if (!string.Equals(text3, b, StringComparison.OrdinalIgnoreCase))
				{
					int frameCount = Time.frameCount;
					if (frameCount - _lastRebuildFrame >= 30)
					{
						_lastRebuildFrame = frameCount;
						LogInfo("Cross-race change detected: '" + text + "' -> '" + text2 + "', triggering rebuild");
						ForceRaceRebuild(__instance, text3);
					}
				}
			}
			catch (Exception ex)
			{
				LogDebug("OnAppearanceStructChange error: " + ex.Message);
			}
		}
	}

	[CompilerGenerated]
	private sealed class <ForceRaceRebuildRoutine>d__23 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public PlayerVisual pv;

		public string targetRaceTag;

		private GameObject <rmo>5__1;

		private IEnumerator <createRoutine>5__2;

		private MethodInfo <method>5__3;

		private Coroutine <co>5__4;

		private RaceModelEquipDisplay <ed>5__5;

		private PlayerAppearanceStruct <s>5__6;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			<rmo>5__1 = null;
			<createRoutine>5__2 = null;
			<method>5__3 = null;
			<co>5__4 = null;
			<ed>5__5 = null;
			<s>5__6 = default(PlayerAppearanceStruct);
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if ((Object)(object)pv == (Object)null)
				{
					return false;
				}
				LogDebug("ForceRaceRebuildRoutine started for race '" + targetRaceTag + "'");
				<rmo>5__1 = null;
				try
				{
					<rmo>5__1 = pv._raceModelObject;
				}
				catch
				{
					<rmo>5__1 = null;
				}
				if ((Object)(object)<rmo>5__1 != (Object)null)
				{
					try
					{
						Object.Destroy((Object)(object)<rmo>5__1);
					}
					catch
					{
					}
					LogDebug("Destroyed old _raceModelObject");
				}
				try
				{
					pv._playerRaceModel = null;
				}
				catch
				{
				}
				try
				{
					pv._raceModelObject = null;
				}
				catch
				{
				}
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<createRoutine>5__2 = null;
				try
				{
					<method>5__3 = typeof(PlayerVisual).GetMethod("Create_PlayerRaceModel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (<method>5__3 != null)
					{
						<createRoutine>5__2 = <method>5__3.Invoke(pv, null) as IEnumerator;
					}
					<method>5__3 = null;
				}
				catch
				{
					<createRoutine>5__2 = null;
				}
				if (<createRoutine>5__2 != null)
				{
					LogDebug("Starting Create_PlayerRaceModel coroutine");
					<co>5__4 = null;
					try
					{
						<co>5__4 = ((MonoBehaviour)pv).StartCoroutine(<createRoutine>5__2);
					}
					catch
					{
						<co>5__4 = null;
					}
					if (<co>5__4 != null)
					{
						<>2__current = <co>5__4;
						<>1__state = 2;
						return true;
					}
					goto IL_01f7;
				}
				LogDebug("Could not get Create_PlayerRaceModel method");
				goto IL_020e;
			case 2:
				<>1__state = -1;
				LogDebug("Create_PlayerRaceModel coroutine completed");
				goto IL_01f7;
			case 3:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 4;
				return true;
			case 4:
				{
					<>1__state = -1;
					try
					{
						<ed>5__5 = null;
						try
						{
							<ed>5__5 = pv._raceModelED;
						}
						catch
						{
							<ed>5__5 = null;
						}
						if ((Object)(object)<ed>5__5 != (Object)null)
						{
							try
							{
								<ed>5__5.Apply_EquipmentVisualDisplay();
							}
							catch
							{
							}
						}
						<ed>5__5 = null;
					}
					catch
					{
					}
					try
					{
						<s>5__6 = pv._playerAppearanceStruct;
						ApplyExtendedValues(pv, <s>5__6);
						<s>5__6 = default(PlayerAppearanceStruct);
					}
					catch
					{
					}
					LogDebug("ForceRaceRebuildRoutine completed for '" + targetRaceTag + "'");
					return false;
				}
				IL_01f7:
				<co>5__4 = null;
				goto IL_020e;
				IL_020e:
				<>2__current = null;
				<>1__state = 3;
				return true;
			}
		}

		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 PLUGIN_GUID = "com.swp.receiver";

	public const string PLUGIN_NAME = "SWP Receiver";

	public const string PLUGIN_VERSION = "1.0.0";

	private static ManualLogSource _logger;

	private static Harmony _harmony;

	private static bool _mainModPresent = false;

	private static bool _initialized = false;

	private static Dictionary<int, int> _lastAppliedFrame = new Dictionary<int, int>();

	private static int _lastPurgeFrame = 0;

	private const int PURGE_INTERVAL_FRAMES = 600;

	private const int ENTRY_MAX_AGE_FRAMES = 300;

	private void Awake()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		_logger = ((BaseUnityPlugin)this).Logger;
		try
		{
			_mainModPresent = DetectMainMod();
			if (_mainModPresent)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"SWP Receiver v1.0.0: Main SWP mod detected, staying dormant.");
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SWP Receiver v1.0.0: Initializing receiver patches...");
			_harmony = new Harmony("com.swp.receiver");
			_harmony.PatchAll(typeof(SWPReceiverPlugin).Assembly);
			_initialized = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SWP Receiver: Successfully initialized.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("SWP Receiver: Failed to initialize: " + ex.Message));
		}
	}

	private void OnDestroy()
	{
		try
		{
			if (_harmony != null && _initialized)
			{
				_harmony.UnpatchSelf();
				_harmony = null;
			}
		}
		catch
		{
		}
	}

	private static bool DetectMainMod()
	{
		try
		{
			Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
			if (pluginInfos != null)
			{
				string[] array = new string[3] { "com.eleen.atlyss.sliderpreset", "com.swp.sliderpreset", "com.eyemod.sliders" };
				string[] array2 = array;
				foreach (string key in array2)
				{
					if (pluginInfos.ContainsKey(key))
					{
						return true;
					}
				}
			}
		}
		catch
		{
		}
		try
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			Assembly[] array3 = assemblies;
			foreach (Assembly assembly in array3)
			{
				try
				{
					if (assembly.GetType("SliderPreset.SliderPresetPlugin") != null)
					{
						return true;
					}
				}
				catch
				{
				}
			}
		}
		catch
		{
		}
		return false;
	}

	internal static void ApplyExtendedValues(PlayerVisual pv, PlayerAppearanceStruct s)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)pv == (Object)null || _mainModPresent || !_initialized)
		{
			return;
		}
		try
		{
			PlayerRaceModel playerRaceModel = pv._playerRaceModel;
			if (!((Object)(object)playerRaceModel == (Object)null))
			{
				Transform armatureTransform = playerRaceModel._armatureTransform;
				if ((Object)(object)armatureTransform != (Object)null)
				{
					armatureTransform.localScale = new Vector3(s._widthWeight, s._heightWeight, s._widthWeight);
				}
				Transform headBoneTransform = playerRaceModel._headBoneTransform;
				if ((Object)(object)headBoneTransform != (Object)null)
				{
					headBoneTransform.localScale = new Vector3(s._headWidth, 1f, 1f);
				}
				playerRaceModel._bellyWeight = s._bellyWeight;
				playerRaceModel._bottomWeight = s._bottomWeight;
				playerRaceModel._boobWeight = s._boobWeight;
				playerRaceModel._torsoWeight = s._torsoWeight;
				playerRaceModel._muzzleWeight = s._muzzleWeight;
				playerRaceModel._armWeight = s._armWeight;
				ApplyBlendShapes(playerRaceModel, s);
			}
		}
		catch (Exception ex)
		{
			LogDebug("ApplyExtendedValues error: " + ex.Message);
		}
	}

	private static void ApplyBlendShapes(PlayerRaceModel raceModel, PlayerAppearanceStruct s)
	{
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: 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)
		try
		{
			SkinnedMeshRenderer baseBodyMesh = raceModel._baseBodyMesh;
			if ((Object)(object)baseBodyMesh != (Object)null && (Object)(object)baseBodyMesh.sharedMesh != (Object)null)
			{
				int blendShapeCount = baseBodyMesh.sharedMesh.blendShapeCount;
				if (blendShapeCount > 0)
				{
					baseBodyMesh.SetBlendShapeWeight(0, s._bellyWeight);
				}
				if (s._bottomWeight < 0f)
				{
					if (blendShapeCount > 1)
					{
						baseBodyMesh.SetBlendShapeWeight(1, 0f);
					}
					int num = 4;
					try
					{
						RaceModelEquipDisplay equipDisplay = raceModel._equipDisplay;
						if ((Object)(object)equipDisplay != (Object)null)
						{
							FieldInfo field = ((object)equipDisplay).GetType().GetField("_hasHeadBlendWeights", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
							if (field != null && (bool)field.GetValue(equipDisplay))
							{
								num = 5;
							}
						}
					}
					catch
					{
					}
					if (blendShapeCount > num)
					{
						baseBodyMesh.SetBlendShapeWeight(num, s._bottomWeight * -1f);
					}
				}
				else if (blendShapeCount > 1)
				{
					baseBodyMesh.SetBlendShapeWeight(1, s._bottomWeight);
				}
				if (blendShapeCount > 2)
				{
					baseBodyMesh.SetBlendShapeWeight(2, s._torsoWeight);
				}
				if (blendShapeCount > 3)
				{
					baseBodyMesh.SetBlendShapeWeight(3, s._muzzleWeight);
				}
			}
			SkinnedMeshRenderer baseBoobMesh = raceModel._baseBoobMesh;
			if ((Object)(object)baseBoobMesh != (Object)null && (Object)(object)baseBoobMesh.sharedMesh != (Object)null && baseBoobMesh.sharedMesh.blendShapeCount > 0)
			{
				baseBoobMesh.SetBlendShapeWeight(0, s._boobWeight);
			}
			SkinnedMeshRenderer baseArmMesh = raceModel._baseArmMesh;
			if ((Object)(object)baseArmMesh != (Object)null && (Object)(object)baseArmMesh.sharedMesh != (Object)null && baseArmMesh.sharedMesh.blendShapeCount > 0)
			{
				baseArmMesh.SetBlendShapeWeight(0, s._armWeight);
			}
		}
		catch (Exception ex)
		{
			LogDebug("ApplyBlendShapes error: " + ex.Message);
		}
	}

	private static void LogDebug(string msg)
	{
		try
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogDebug((object)("[SWP_Receiver] " + msg));
			}
		}
		catch
		{
		}
	}

	private static void LogInfo(string msg)
	{
		try
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogInfo((object)("[SWP_Receiver] " + msg));
			}
		}
		catch
		{
		}
	}

	private static string NormalizeRaceName(string raceName)
	{
		if (string.IsNullOrEmpty(raceName))
		{
			return "";
		}
		return raceName.Replace(" ", "").ToLowerInvariant();
	}

	private static void TryPurgeOldEntries(int currentFrame)
	{
		if (currentFrame - _lastPurgeFrame < 600)
		{
			return;
		}
		_lastPurgeFrame = currentFrame;
		try
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, int> item in _lastAppliedFrame)
			{
				if (currentFrame - item.Value > 300)
				{
					list.Add(item.Key);
				}
			}
			foreach (int item2 in list)
			{
				_lastAppliedFrame.Remove(item2);
			}
		}
		catch
		{
		}
	}

	private static void ForceRaceRebuild(PlayerVisual pv, string targetRaceTag)
	{
		try
		{
			if (!((Object)(object)pv == (Object)null))
			{
				((MonoBehaviour)pv).StartCoroutine(ForceRaceRebuildRoutine(pv, targetRaceTag));
			}
		}
		catch (Exception ex)
		{
			LogDebug("ForceRaceRebuild error: " + ex.Message);
		}
	}

	[IteratorStateMachine(typeof(<ForceRaceRebuildRoutine>d__23))]
	private static IEnumerator ForceRaceRebuildRoutine(PlayerVisual pv, string targetRaceTag)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ForceRaceRebuildRoutine>d__23(0)
		{
			pv = pv,
			targetRaceTag = targetRaceTag
		};
	}
}