Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of JohnPorkMod v1.2.0
plugins/JohnPorkMod.dll
Decompiled 4 days agousing 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<AudioSource, AudioSourceData> audioSourceData = new Dictionary<AudioSource, AudioSourceData>(); internal static ConfigEntry<int> configMinInterval; internal static ConfigEntry<int> 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<int>("Timer Settings", "MinInterval", 15, new ConfigDescription("Minimum wait time in seconds before the phone rings.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 200), Array.Empty<object>())); configMaxInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Timer Settings", "MaxInterval", 100, new ConfigDescription("Maximum wait time in seconds before the phone rings.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 300), Array.Empty<object>())); 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<TextureReplacer>(); } } 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<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) { 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<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()); } 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<Renderer>(); 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(); } } }