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("2.0.1.0")] [assembly: AssemblyInformationalVersion("2.0.1+7023f56636b0a23446304da94ddb1c1dc23741dc")] [assembly: AssemblyProduct("smert-v-nishite")] [assembly: AssemblyTitle("smert-v-nishite")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.1.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", "Smert v Nishite", "2.0.1")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static AudioClip replacementAudio; internal static Texture2D replacementTexture; internal static Dictionary audioSourceData = new Dictionary(); 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(); } } 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(text); Logger.LogDebug((object)("Ringtone loaded: " + text)); } else if (text.EndsWith(".png")) { replacementTexture = val.LoadAsset(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 d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public TextureReplacer <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 processedMaterials = new HashSet(); private static readonly Dictionary modifiedAtlasCache = new Dictionary(); private static readonly int EmissionMapId = Shader.PropertyToID("_EmissionMap"); private float lastScanTime; private void Start() { ((MonoBehaviour)this).StartCoroutine(InitialScan()); } [IteratorStateMachine(typeof(d__8))] private IEnumerator InitialScan() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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(); 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 = "2.0.1"; } }