Decompiled source of JohnPorkMod v1.0.1

plugins/JohnPorkMod.dll

Decompiled 13 hours 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("kossnikita")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("smert-v-nishite")]
[assembly: AssemblyTitle("smert-v-nishite")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace smert_v_nishite
{
	public class AudioSourceData
	{
		public AudioClip OriginalClip { get; set; }

		public AudioClip RealClip
		{
			get
			{
				using (new SpoofBypass())
				{
					return Source.clip;
				}
			}
			set
			{
				using (new SpoofBypass())
				{
					Source.clip = value;
				}
			}
		}

		public AudioSource Source { get; }

		private AudioSourceData(AudioSource source)
		{
			Source = source;
		}

		public static AudioSourceData GetOrCreate(AudioSource source)
		{
			if (Plugin.audioSourceData.TryGetValue(source, out var value))
			{
				return value;
			}
			value = new AudioSourceData(source)
			{
				OriginalClip = source.clip
			};
			Plugin.audioSourceData[source] = value;
			return value;
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	public class AudioSourcePatch
	{
		[ThreadStatic]
		internal static bool bypassSpoofing;

		[HarmonyPrefix]
		[HarmonyPatch("Play", new Type[] { })]
		[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
		[HarmonyPatch("Play", new Type[] { typeof(double) })]
		private static bool Play(AudioSource __instance)
		{
			AudioSourceData orCreate = AudioSourceData.GetOrCreate(__instance);
			AudioClip originalClip = orCreate.OriginalClip;
			AudioClip replacedSound = Plugin.GetReplacedSound(((originalClip != null) ? ((Object)originalClip).name : null) ?? "");
			if ((Object)(object)replacedSound == (Object)null)
			{
				return true;
			}
			orCreate.RealClip = replacedSound;
			using (new SpoofBypass())
			{
				__instance.clip = replacedSound;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("PlayOneShot", new Type[]
		{
			typeof(AudioClip),
			typeof(float)
		})]
		private static bool PlayOneShot(ref AudioClip clip)
		{
			AudioClip obj = clip;
			AudioClip replacedSound = Plugin.GetReplacedSound(((obj != null) ? ((Object)obj).name : null) ?? "");
			if ((Object)(object)replacedSound != (Object)null)
			{
				clip = replacedSound;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static bool ClipSetter(AudioSource __instance, AudioClip value)
		{
			if (bypassSpoofing)
			{
				return true;
			}
			if (Plugin.audioSourceData.TryGetValue(__instance, out var value2) && (Object)(object)value2.OriginalClip == (Object)(object)value)
			{
				return false;
			}
			AudioSourceData.GetOrCreate(__instance).OriginalClip = value;
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void ClipGetter(AudioSource __instance, ref AudioClip __result)
		{
			if (!bypassSpoofing && Plugin.audioSourceData.TryGetValue(__instance, out var value) && (Object)(object)value.OriginalClip != (Object)null)
			{
				__result = value.OriginalClip;
			}
		}
	}
	public class SpoofBypass : IDisposable
	{
		public SpoofBypass()
		{
			AudioSourcePatch.bypassSpoofing = true;
		}

		public void Dispose()
		{
			AudioSourcePatch.bypassSpoofing = false;
		}
	}
	[BepInPlugin("smert-v-nishite", "JohnPorkMod", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static AudioClip replacementAudio;

		internal static Texture2D replacementTexture;

		internal static Dictionary<AudioSource, AudioSourceData> audioSourceData = new Dictionary<AudioSource, AudioSourceData>();

		private static bool textureReplacerInitialized;

		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			if (LoadAssetBundle())
			{
				new Harmony("smert-v-nishite").PatchAll();
				SceneManager.sceneLoaded += OnSceneLoaded;
				Logger.LogInfo((object)"Plugin loaded!");
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!textureReplacerInitialized)
			{
				textureReplacerInitialized = true;
				GameObject val = new GameObject("TextureReplacer");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<TextureReplacer>();
			}
		}

		private bool LoadAssetBundle()
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("smert_v_nishite.smert_v_nishite");
			if (stream == null)
			{
				Logger.LogError((object)"Embedded asset bundle not found.");
				return false;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			AssetBundle val = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)"Failed to load asset bundle.");
				return false;
			}
			string[] allAssetNames = val.GetAllAssetNames();
			foreach (string text in allAssetNames)
			{
				if (text.EndsWith(".ogg"))
				{
					replacementAudio = val.LoadAsset<AudioClip>(text);
					Logger.LogDebug((object)("Ringtone loaded: " + text));
				}
				else if (text.EndsWith(".png"))
				{
					replacementTexture = val.LoadAsset<Texture2D>(text);
					Logger.LogDebug((object)("Screen loadded: " + text));
				}
			}
			return true;
		}

		public static AudioClip GetReplacedSound(string originalName)
		{
			if (!(originalName.ToLowerInvariant() == "phone ringtone"))
			{
				return null;
			}
			return replacementAudio;
		}
	}
	public class TextureReplacer : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <InitialScan>d__8 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public TextureReplacer <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Expected O, but got Unknown
				int num = <>1__state;
				TextureReplacer textureReplacer = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					textureReplacer.ScanRenderers();
					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();
			}
		}

		private const string ATLAS_NAME = "arctic small valuables_defaultmaterial_emissive";

		private const int OVERLAY_X = 241;

		private const int OVERLAY_Y_FROM_TOP = 107;

		private static readonly HashSet<int> processedMaterials = new HashSet<int>();

		private static readonly Dictionary<int, Texture2D> modifiedAtlasCache = new Dictionary<int, Texture2D>();

		private static readonly int EmissionMapId = Shader.PropertyToID("_EmissionMap");

		private float lastScanTime;

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(InitialScan());
		}

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

		private void Update()
		{
			if (!(Time.time - lastScanTime < 2f))
			{
				lastScanTime = Time.time;
				ScanRenderers();
			}
		}

		private void ScanRenderers()
		{
			Renderer[] array = Object.FindObjectsOfType<Renderer>();
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					TryReplacePropertyBlock(val);
					TryReplaceMaterials(val);
				}
			}
		}

		private void TryReplacePropertyBlock(Renderer renderer)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			MaterialPropertyBlock val = new MaterialPropertyBlock();
			renderer.GetPropertyBlock(val);
			Texture texture = val.GetTexture(EmissionMapId);
			Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null);
			if (val2 != null && !(((Object)val2).name?.ToLowerInvariant() != "arctic small valuables_defaultmaterial_emissive"))
			{
				Texture2D orCreateModifiedAtlas = GetOrCreateModifiedAtlas(val2);
				if (!((Object)(object)orCreateModifiedAtlas == (Object)null))
				{
					val.SetTexture(EmissionMapId, (Texture)(object)orCreateModifiedAtlas);
					renderer.SetPropertyBlock(val);
				}
			}
		}

		private void TryReplaceMaterials(Renderer renderer)
		{
			Material[] sharedMaterials = renderer.sharedMaterials;
			if (sharedMaterials == null)
			{
				return;
			}
			Material[] array = sharedMaterials;
			foreach (Material val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				if (!processedMaterials.Contains(instanceID))
				{
					processedMaterials.Add(instanceID);
					if (!TryReplaceMaterialTexture(val, "_EmissionMap") && !TryReplaceMaterialTexture(val, "_MainTex"))
					{
						TryReplaceMaterialTexture(val, "_BaseMap");
					}
				}
			}
		}

		private bool TryReplaceMaterialTexture(Material mat, string prop)
		{
			if (!mat.HasProperty(prop))
			{
				return false;
			}
			Texture texture = mat.GetTexture(prop);
			Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null);
			if (val == null)
			{
				return false;
			}
			if (((Object)val).name?.ToLowerInvariant() != "arctic small valuables_defaultmaterial_emissive")
			{
				return false;
			}
			Texture2D orCreateModifiedAtlas = GetOrCreateModifiedAtlas(val);
			if ((Object)(object)orCreateModifiedAtlas == (Object)null)
			{
				return false;
			}
			mat.SetTexture(prop, (Texture)(object)orCreateModifiedAtlas);
			if (prop == "_EmissionMap")
			{
				try
				{
					mat.EnableKeyword("_EMISSION");
				}
				catch
				{
				}
			}
			return true;
		}

		private Texture2D GetOrCreateModifiedAtlas(Texture2D original)
		{
			int instanceID = ((Object)original).GetInstanceID();
			if (modifiedAtlasCache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Texture2D val = CreateModifiedAtlas(original);
			if ((Object)(object)val != (Object)null)
			{
				modifiedAtlasCache[instanceID] = val;
			}
			return val;
		}

		private Texture2D CreateModifiedAtlas(Texture2D original)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null || (Object)(object)Plugin.replacementTexture == (Object)null)
			{
				return null;
			}
			Texture2D replacementTexture = Plugin.replacementTexture;
			int num = ((Texture)original).height - 107 - ((Texture)replacementTexture).height;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)original).width, ((Texture)original).height, 0, (RenderTextureFormat)0);
			Graphics.Blit((Texture)(object)original, temporary);
			Texture2D val = new Texture2D(((Texture)original).width, ((Texture)original).height, (TextureFormat)4, false, true);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)original).width, (float)((Texture)original).height), 0, 0);
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color[] array = ReadPixels(replacementTexture);
			if (array == null)
			{
				return null;
			}
			val.SetPixels(241, num, ((Texture)replacementTexture).width, ((Texture)replacementTexture).height, array);
			val.Apply(false);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)2;
			return val;
		}

		private Color[] ReadPixels(Texture2D tex)
		{
			//IL_0029: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)tex).width, ((Texture)tex).height, 0, (RenderTextureFormat)0);
			Graphics.Blit((Texture)(object)tex, temporary);
			Texture2D val = new Texture2D(((Texture)tex).width, ((Texture)tex).height, (TextureFormat)4, false);
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = temporary;
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color[] pixels = val.GetPixels();
			Object.Destroy((Object)val);
			return pixels;
		}

		private void OnDestroy()
		{
			processedMaterials.Clear();
			foreach (Texture2D value in modifiedAtlasCache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			modifiedAtlasCache.Clear();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "smert-v-nishite";

		public const string PLUGIN_NAME = "smert-v-nishite";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}