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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Bengi")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("JohnPorkMod")] [assembly: AssemblyTitle("JohnPorkMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [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 JohnPorkMod { public static class MyPluginInfo { public const string PLUGIN_GUID = "JohnPorkMod"; public const string PLUGIN_NAME = "JohnPorkMod"; public const string PLUGIN_VERSION = "1.2.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("JohnPorkMod", "JohnPorkMod", "1.1.3")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(PhoneValuable), "Start")] internal static class PhoneValuableStartPatch { [HarmonyPostfix] private static void Postfix(PhoneValuable __instance) { if (!((Object)(object)__instance == (Object)null)) { __instance.ringIntervalTimer = 0f; Logger.LogInfo((object)"[JohnPorkMod] First Time Phone Ringing"); } } } [HarmonyPatch(typeof(PhoneValuable), "Update")] internal static class PhoneValuableUpdatePatch { private static float accumulatedTime = 0f; private static float targetInterval = -1f; [HarmonyPostfix] private static void Postfix(PhoneValuable __instance) { if ((Object)(object)__instance == (Object)null) { return; } if (targetInterval < 0f) { targetInterval = configMinInterval.Value; } if (!__instance.phoneRinging) { accumulatedTime += Time.deltaTime; if (__instance.ringIntervalTimer > 0f) { __instance.ringIntervalTimer = targetInterval; } if (accumulatedTime >= targetInterval) { __instance.ringIntervalTimer = 0f; accumulatedTime = 0f; int num = configMinInterval.Value; int value = configMaxInterval.Value; if (num > value) { num = value; } targetInterval = Random.Range(num, value + 1); Logger.LogInfo((object)$"[JohnPorkMod] Next interval from Config: {targetInterval}s"); } } else { accumulatedTime = 0f; } } } internal static ManualLogSource Logger; internal static AudioClip replacementAudio; internal static Texture2D replacementTexture; internal static Dictionary audioSourceData = new Dictionary(); internal static ConfigEntry configMinInterval; internal static ConfigEntry configMaxInterval; private static bool textureReplacerInitialized; private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; configMinInterval = ((BaseUnityPlugin)this).Config.Bind("Timer Settings", "MinInterval", 15, new ConfigDescription("Minimum wait time in seconds before the phone rings.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 200), Array.Empty())); configMaxInterval = ((BaseUnityPlugin)this).Config.Bind("Timer Settings", "MaxInterval", 100, new ConfigDescription("Maximum wait time in seconds before the phone rings.", (AcceptableValueBase)(object)new AcceptableValueRange(20, 300), Array.Empty())); if (LoadAssetBundle()) { new Harmony("JohnPorkMod").PatchAll(); SceneManager.sceneLoaded += OnSceneLoaded; Logger.LogInfo((object)"Plugin loaded!"); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!textureReplacerInitialized) { textureReplacerInitialized = true; GameObject val = new GameObject("TextureReplacer"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); } } private bool LoadAssetBundle() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.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) { return (originalName.ToLowerInvariant() == "phone ringtone") ? replacementAudio : null; } } public class TextureReplacer : MonoBehaviour { 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()); } private IEnumerator InitialScan() { yield return (object)new WaitForSeconds(0.5f); ScanRenderers(); } 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0095: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) 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)(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(); } } }