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 ExplosiveSprayPaint v1.1.5
BepInEx\plugins\ExplosiveSprayPaint\ExplosiveSprayPaint.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExplosiveSprayPaint.Config; using ExplosiveSprayPaint.Networking; using ExplosiveSprayPaint.Patches; using ExplosiveSprayPaint.Utilities; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Rendering.HighDefinition; [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("ExplosiveSprayPaint")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ExplosiveSprayPaint")] [assembly: AssemblyTitle("ExplosiveSprayPaint")] [assembly: AssemblyVersion("1.0.0.0")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ExplosiveSprayPaint { [BepInPlugin("huntedbyacreature.explosivespraypaint", "ExplosiveSprayPaint", "1.1.5")] public sealed class Plugin : BaseUnityPlugin { public const string ModGuid = "huntedbyacreature.explosivespraypaint"; public const string ModName = "ExplosiveSprayPaint"; public const string ModVersion = "1.1.5"; private Harmony? _harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ExplosiveSprayPaintConfig ModConfig { get; private set; } private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig = new ExplosiveSprayPaintConfig(((BaseUnityPlugin)this).Config); _harmony = new Harmony("huntedbyacreature.explosivespraypaint"); SprayPaintItemPatches.Apply(_harmony); _harmony.PatchAll(typeof(Plugin).Assembly); SprayPaintRuntimeWatcher.Register(); SprayCanExplosionNetworking.Register(); Log.LogInfo((object)string.Format("{0} {1} loaded. DebugLogging={2}, TreatSprayUseAsShake={3}, GlowInTheDarkPaint={4}, FunnyExplosionPhysics={5}, ExplosionChance={6:0.##}%.", "ExplosiveSprayPaint", "1.1.5", ModConfig.EnableDebugLogging.Value, ModConfig.TreatSprayUseAsShake.Value, ModConfig.GlowInTheDarkPaint.Value, ModConfig.EnableFunnyExplosionPhysics.Value, ModConfig.ExplosionChancePercent.Value)); } private void Update() { SprayPaintRuntimeWatcher.Tick(); } private void OnDestroy() { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Plugin component OnDestroy called; leaving runtime hooks active for this session."); } } } } namespace ExplosiveSprayPaint.Utilities { internal static class ExplosionEffectUtility { private const int EnemyCollisionMask = 524288; private const float FunnyNormalPhysicsForce = 35f; private const float FunnyCatastrophicPhysicsForce = 85f; private const float FunnyNormalPlayerKnockback = 13f; private const float FunnyCatastrophicPlayerKnockback = 32f; private const float FunnyNormalVerticalKnockback = 5f; private const float FunnyCatastrophicVerticalKnockback = 12f; internal static Vector3 GetExplosionPosition(SprayPaintItem sprayPaintItem) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)sprayPaintItem).transform; PlayerControllerB playerHeldBy = ((GrabbableObject)sprayPaintItem).playerHeldBy; if ((Object)(object)playerHeldBy != (Object)null) { if (!((Object)(object)playerHeldBy.gameplayCamera != (Object)null)) { return ((Component)playerHeldBy).transform.position + Vector3.up * 1.2f + ((Component)playerHeldBy).transform.forward * 0.35f; } return ((Component)playerHeldBy.gameplayCamera).transform.position + ((Component)playerHeldBy.gameplayCamera).transform.forward * 0.35f - Vector3.up * 0.25f; } return transform.position; } internal static void PlayClientSideExplosion(ExplosionMessage message, SprayPaintItem? sprayPaintItem) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)$"Playing client explosion. catastrophic={message.Catastrophic}, blastRadius={message.BlastRadius:0.00}, paintRadius={message.PaintRadius:0.00}, paintCount={message.PaintCount}, color={ColorUtility.ToHtmlStringRGBA(message.PaintColor)}, hasSprayItem={(Object)(object)sprayPaintItem != (Object)null}."); } TrySpawnVanillaExplosion(message.Position, message.BlastRadius, message.PhysicsForce); PaintDecalUtility.SpawnPaintBurst(sprayPaintItem, message.Position, message.PaintColor, message.PaintRadius, message.PaintCount, message.RandomSeed); ParticleUtility.SpawnPaintParticles(message.Position, message.PaintColor, message.BlastRadius, message.Catastrophic); TryShakeCamera(message.Position, message.BlastRadius, message.Catastrophic); TryShowHudNotification(message); } internal static void ApplyServerSideDamageAndNoise(ExplosionMessage message) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) float blastRadius = message.BlastRadius; int damage = (message.Catastrophic ? Plugin.ModConfig.CatastrophicPlayerDamage.Value : Plugin.ModConfig.NormalPlayerDamage.Value); int damage2 = (message.Catastrophic ? Plugin.ModConfig.CatastrophicEnemyDamage.Value : Plugin.ModConfig.NormalEnemyDamage.Value); DamageNearbyPlayers(message.Position, blastRadius, damage, message.Catastrophic); DamageNearbyEnemies(message.Position, blastRadius, damage2); RoundManager instance = RoundManager.Instance; if (instance != null) { instance.PlayAudibleNoise(message.Position, message.Catastrophic ? (blastRadius * 2.5f) : (blastRadius * 1.6f), message.Catastrophic ? 1f : 0.55f, 0, false, 0); } } private static void TrySpawnVanillaExplosion(Vector3 position, float radius, float physicsForce) { //IL_018b: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo methodInfo = AccessTools.Method(typeof(Landmine), "SpawnExplosion", (Type[])null, (Type[])null); if (methodInfo == null) { return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { string text = parameters[i].Name ?? string.Empty; object[] array2 = array; int num = i; object obj; switch (text) { case "explosionPosition": case "position": obj = position; break; case "spawnExplosionEffect": obj = true; break; case "killRange": obj = 0f; break; case "damageRange": obj = radius; break; case "nonLethalDamage": case "damage": obj = 0; break; case "physicsForce": obj = physicsForce; break; case "overridePrefab": obj = null; break; case "goThroughCar": obj = true; break; default: obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType)); break; } array2[num] = obj; } methodInfo.Invoke(null, array); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not spawn vanilla explosion effect: " + ex.Message)); } } private static void DamageNearbyPlayers(Vector3 position, float radius, int damage, bool catastrophic) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) if (damage <= 0 || StartOfRound.Instance?.allPlayerScripts == null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead) { continue; } float num = Vector3.Distance(position, ((Component)val).transform.position); if (!(num > radius)) { float num2 = Mathf.Clamp01(1f - num / Mathf.Max(radius, 0.01f)); int damage2 = Mathf.Max(1, Mathf.RoundToInt((float)damage * Mathf.Lerp(0.45f, 1f, num2))); Vector3 val2 = ((Component)val).transform.position - position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.001f) { val2 = ((Component)val).transform.forward; } float num3 = (catastrophic ? GetCatastrophicPlayerKnockback() : GetNormalPlayerKnockback()); Vector3 val3 = ((Vector3)(ref val2)).normalized * num3; val3.y = GetVerticalPlayerKnockback(catastrophic); try { InvokeDamagePlayer(val, damage2, val3); SprayPaintIntrospection.AddExternalForce(val, Plugin.ModConfig.EnableFunnyExplosionPhysics.Value ? val3 : ClampPlayerForce(val3)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not damage player " + val.playerUsername + ": " + ex.Message)); } } } } private static void DamageNearbyEnemies(Vector3 position, float radius, int damage) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (damage <= 0) { return; } HashSet<EnemyAI> hashSet = new HashSet<EnemyAI>(); Collider[] array = Physics.OverlapSphere(position, radius, 524288, (QueryTriggerInteraction)2); for (int i = 0; i < array.Length; i++) { EnemyAI componentInParent = ((Component)array[i]).GetComponentInParent<EnemyAI>(); if (!((Object)(object)componentInParent == (Object)null) && !componentInParent.isEnemyDead && hashSet.Add(componentInParent)) { try { InvokeHitEnemy(componentInParent, damage); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not damage enemy " + componentInParent.enemyType?.enemyName + ": " + ex.Message)); } } } } private static void TryShakeCamera(Vector3 position, float radius, bool catastrophic) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ModConfig.EnableScreenShake.Value || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null || Vector3.Distance(((Component)GameNetworkManager.Instance.localPlayerController).transform.position, position) > radius * 1.75f) { return; } try { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ShakeCamera((ScreenShakeType)catastrophic); } } catch { } } private static void TryShowHudNotification(ExplosionMessage message) { if (!Plugin.ModConfig.EnableHudNotification.Value || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null || GameNetworkManager.Instance.localPlayerController.actualClientId != message.HolderClientId) { return; } try { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("Explosive Spray Paint", "The can ruptured!", true, false, "ESP_CanRuptured"); } } catch { } } internal static float GetBlastRadius(bool catastrophic) { return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicBlastRadius.Value : Plugin.ModConfig.NormalBlastRadius.Value, 0.5f, catastrophic ? 8f : 4.5f); } internal static float GetPhysicsForce(bool catastrophic) { if (Plugin.ModConfig.EnableFunnyExplosionPhysics.Value) { if (!catastrophic) { return 35f; } return 85f; } return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPhysicsForce.Value : Plugin.ModConfig.NormalPhysicsForce.Value, 0f, catastrophic ? 6f : 3f); } internal static float GetPaintRadius(bool catastrophic) { return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPaintSplatterRadius.Value : Plugin.ModConfig.NormalPaintSplatterRadius.Value, 0.5f, catastrophic ? 12f : 7f); } internal static int GetPaintCount(bool catastrophic) { return Mathf.Clamp(catastrophic ? Plugin.ModConfig.CatastrophicPaintSplats.Value : Plugin.ModConfig.NormalPaintSplats.Value, 0, catastrophic ? 240 : 140); } private static Vector3 ClampPlayerForce(Vector3 force) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(force.x, 0f, force.z); float num = 3f; if (((Vector3)(ref val)).magnitude > num) { val = ((Vector3)(ref val)).normalized * num; } return new Vector3(val.x, Mathf.Clamp(force.y, -0.1f, Plugin.ModConfig.MaxVerticalKnockback.Value), val.z); } private static float GetNormalPlayerKnockback() { if (!Plugin.ModConfig.EnableFunnyExplosionPhysics.Value) { return Plugin.ModConfig.NormalPlayerKnockback.Value; } return 13f; } private static float GetCatastrophicPlayerKnockback() { if (!Plugin.ModConfig.EnableFunnyExplosionPhysics.Value) { return Plugin.ModConfig.CatastrophicPlayerKnockback.Value; } return 32f; } private static float GetVerticalPlayerKnockback(bool catastrophic) { if (Plugin.ModConfig.EnableFunnyExplosionPhysics.Value) { if (!catastrophic) { return 5f; } return 12f; } return Mathf.Min(Plugin.ModConfig.MaxVerticalKnockback.Value, catastrophic ? 0.7f : 0.35f); } private static void InvokeDamagePlayer(PlayerControllerB player, int damage, Vector3 force) { //IL_0180: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "DamagePlayer", (Type[])null, (Type[])null); if (methodInfo == null) { return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { string text = parameters[i].Name ?? string.Empty; object[] array2 = array; int num = i; object obj; switch (text) { case "damageNumber": case "damage": obj = damage; break; case "hasDamageSFX": obj = true; break; case "callRPC": obj = true; break; case "causeOfDeath": obj = (object)(CauseOfDeath)0; break; case "deathAnimation": obj = 0; break; case "fallDamage": obj = false; break; case "force": obj = force; break; default: obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType)); break; } array2[num] = obj; } methodInfo.Invoke(player, array); } private static void InvokeHitEnemy(EnemyAI enemy, int damage) { MethodInfo methodInfo = AccessTools.Method(((object)enemy).GetType(), "HitEnemy", (Type[])null, (Type[])null); if (methodInfo == null) { return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { string text = parameters[i].Name ?? string.Empty; object[] array2 = array; int num = i; object obj; switch (text) { case "force": case "damage": obj = damage; break; case "playerWhoHit": obj = null; break; case "playHitSFX": obj = true; break; case "hitID": obj = -1; break; default: obj = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType)); break; } array2[num] = obj; } methodInfo.Invoke(enemy, array); } private static object? GetDefaultValue(Type type) { if (!type.IsValueType) { return null; } return Activator.CreateInstance(type); } } internal static class PaintDecalUtility { private const float SurfaceOffset = 0.018f; internal static void SpawnPaintBurst(SprayPaintItem? sprayPaintItem, Vector3 origin, Color color, float radius, int count, int seed) { //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (count <= 0 || radius <= 0f) { return; } GameObject val = TryGetPaintPrefab(sprayPaintItem); State state = Random.state; Random.InitState(seed); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = count * 5; LogDebug($"Paint burst starting. origin={origin}, radius={radius:0.00}, targetCount={count}, color={ColorUtility.ToHtmlStringRGBA(color)}, hasSprayItem={(Object)(object)sprayPaintItem != (Object)null}, hasVanillaPrefab={(Object)(object)val != (Object)null}."); try { for (int i = 0; i < num6; i++) { if (num >= count) { break; } if (!TryFindPaintSurface(origin, radius, out var hit)) { num3++; continue; } num2++; float size = Random.Range(0.28f, 0.95f) * ((Random.value < 0.12f) ? 1.45f : 1f); if (Plugin.ModConfig.UseVanillaPaintPlacement.Value && (Object)(object)sprayPaintItem != (Object)null && SprayPaintIntrospection.TryAddVanillaPaint(sprayPaintItem, ((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal)) { num4++; } SpawnSingleSplat(val, hit, color, size); num5++; num++; } LogDebug($"Paint burst finished. attempts={num6}, raycastHits={num2}, rejectedHits={num3}, visibleSplats={num}/{count}, vanillaPlacements={num4}, fallbackSplats={num5}."); } finally { Random.state = state; } } private static bool TryFindPaintSurface(Vector3 origin, float radius, out RaycastHit hit) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) float value = Random.value; Vector2 val = Random.insideUnitCircle * radius; if (value < 0.34f) { return TryRaycastPaintSurface(origin + new Vector3(val.x, 2.2f + Random.Range(0f, 0.7f), val.y), Vector3.down, 5.5f, out hit); } if (value < 0.74f) { Vector2 insideUnitCircle = Random.insideUnitCircle; Vector3 val2 = Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector2.op_Implicit(Vector2.right); } Vector3 val3 = new Vector3(val2.x, Random.Range(-0.2f, 0.35f), val2.y); Vector3 normalized = ((Vector3)(ref val3)).normalized; return TryRaycastPaintSurface(origin + Vector3.up * Random.Range(-0.2f, 1.4f), normalized, radius + 2f, out hit); } Vector3 onUnitSphere = Random.onUnitSphere; if (onUnitSphere.y > 0.75f) { onUnitSphere.y *= -1f; } return TryRaycastPaintSurface(origin + Random.insideUnitSphere * 0.35f, ((Vector3)(ref onUnitSphere)).normalized, radius + 2.5f, out hit); } private static bool TryRaycastPaintSurface(Vector3 origin, Vector3 direction, float distance, out RaycastHit hit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) RaycastHit[] array = Physics.RaycastAll(origin, ((Vector3)(ref direction)).normalized, distance, -1, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; foreach (RaycastHit val in array2) { if (IsValidPaintSurface(val)) { hit = val; return true; } } hit = default(RaycastHit); return false; } private static bool IsValidPaintSurface(RaycastHit hit) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) Collider collider = ((RaycastHit)(ref hit)).collider; if ((Object)(object)collider == (Object)null || !collider.enabled || collider.isTrigger) { return false; } if ((Object)(object)((Component)collider).GetComponentInParent<PlayerControllerB>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<GrabbableObject>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<EnemyAI>() != (Object)null) { return false; } Renderer val = ((Component)collider).GetComponent<Renderer>() ?? ((Component)collider).GetComponentInParent<Renderer>() ?? ((Component)collider).GetComponentInChildren<Renderer>(); if ((Object)(object)val == (Object)null || !val.enabled) { return false; } Vector3 normal = ((RaycastHit)(ref hit)).normal; return ((Vector3)(ref normal)).sqrMagnitude > 0.8f; } private static GameObject? TryGetPaintPrefab(SprayPaintItem? sprayPaintItem) { if ((Object)(object)sprayPaintItem == (Object)null) { return null; } return SprayPaintIntrospection.GetObjectField<GameObject>(sprayPaintItem, new string[3] { "sprayPaintPrefab", "paintPrefab", "sprayDecalPrefab" }); } private static void SpawnSingleSplat(GameObject? vanillaPaintPrefab, RaycastHit hit, Color color, float size) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) GameObject obj = SpawnFallbackSplat(hit, color, size * Random.Range(0.85f, 1.25f)); ((Object)obj).name = "ExplosiveSprayPaint_VisibleSplat"; obj.AddComponent<TemporaryObject>().Initialize(Plugin.ModConfig.PaintLifetimeSeconds.Value, destroyInstancedMaterials: true); } private static GameObject SpawnFallbackSplat(RaycastHit hit, Color color, float size) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ExplosiveSprayPaint_FallbackSplat"); Vector3 normal = ((RaycastHit)(ref hit)).normal; Vector3 normalized = ((Vector3)(ref normal)).normalized; val.transform.position = ((RaycastHit)(ref hit)).point + normalized * 0.018f; val.transform.rotation = SurfaceRotationForQuad(normalized); val.transform.Rotate(Vector3.forward, Random.Range(0f, 360f), (Space)1); val.transform.SetParent(((Component)((RaycastHit)(ref hit)).collider).transform, true); GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = "PaintQuad"; obj.transform.SetParent(val.transform, false); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = new Vector3(size, size * Random.Range(0.55f, 1.25f), 1f); RemoveColliders(obj); obj.GetComponent<Renderer>().material = CreateQuadMaterial(color, Random.Range(0, int.MaxValue)); return val; } private static Material CreateQuadMaterial(Color color, int seed) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(FindPaintShader()); Texture2D val3 = (Texture2D)(object)(val.mainTexture = (Texture)(object)CreateSplatTexture(color, seed)); ApplyColor(val, Color.white); DisableEmission(val); val.renderQueue = 3000; if (val.HasProperty("_SurfaceType")) { val.SetFloat("_SurfaceType", 1f); val.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); } if (val.HasProperty("_BlendMode")) { val.SetFloat("_BlendMode", 0f); } if (val.HasProperty("_SrcBlend")) { val.SetFloat("_SrcBlend", 5f); } if (val.HasProperty("_DstBlend")) { val.SetFloat("_DstBlend", 10f); } if (val.HasProperty("_ZWrite")) { val.SetFloat("_ZWrite", 0f); } if (val.HasProperty("_BaseColorMap")) { val.SetTexture("_BaseColorMap", (Texture)(object)val3); } if (val.HasProperty("_UnlitColorMap")) { val.SetTexture("_UnlitColorMap", (Texture)(object)val3); } if (val.HasProperty("_CullMode")) { val.SetFloat("_CullMode", 0f); } if (val.HasProperty("_Cull")) { val.SetFloat("_Cull", 0f); } return val; } private static Shader FindPaintShader() { if (Plugin.ModConfig.GlowInTheDarkPaint.Value) { return Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Transparent") ?? Shader.Find("HDRP/Unlit") ?? Shader.Find("Standard"); } return Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Transparent"); } private static Texture2D CreateSplatTexture(Color color, int seed) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = "ExplosiveSprayPaint_SplatTexture", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; State state = Random.state; Random.InitState(seed); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(63f * Random.Range(0.43f, 0.57f), 63f * Random.Range(0.43f, 0.57f)); float num = Random.Range(17f, 25f); float num2 = Random.Range(0.8f, 1.25f); float num3 = Random.Range(0.75f, 1.25f); Vector2 val3 = default(Vector2); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { ((Vector2)(ref val3))..ctor(((float)j - val2.x) / num2, ((float)i - val2.y) / num3); float magnitude = ((Vector2)(ref val3)).magnitude; float num4 = Mathf.PerlinNoise((float)j * 0.16f + (float)seed * 0.001f, (float)i * 0.16f - (float)seed * 0.001f); float num5 = Mathf.Clamp01((num * Mathf.Lerp(0.72f, 1.22f, num4) - magnitude) / 5.5f); for (int k = 0; k < 5; k++) { float num6 = (float)k / 5f * MathF.PI * 2f + (float)seed * 0.0001f; Vector2 val4 = val2 + new Vector2(Mathf.Cos(num6), Mathf.Sin(num6)) * Random.Range(15f, 27f); float num7 = Vector2.Distance(new Vector2((float)j, (float)i), val4); num5 = Mathf.Max(num5, Mathf.Clamp01((Random.Range(3f, 7f) - num7) / 2f)); } Color val5 = color; val5.a = num5 * 0.94f; val.SetPixel(j, i, val5); } } val.Apply(false, false); Random.state = state; return val; } private static void LogDebug(string message) { if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)message); } } private static void ApplyColor(Material material, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) material.color = color; if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } } private static void DisableEmission(Material material) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) material.DisableKeyword("_EMISSION"); material.DisableKeyword("_EMISSIVE_COLOR_MAP"); if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); } if (material.HasProperty("_EmissiveColor")) { material.SetColor("_EmissiveColor", Color.black); } if (material.HasProperty("_EmissiveIntensity")) { material.SetFloat("_EmissiveIntensity", 0f); } } private static Quaternion SurfaceRotationForQuad(Vector3 normal) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Quaternion.LookRotation(normal, GetStableUp(normal)); } private static Vector3 GetStableUp(Vector3 normal) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.Cross(normal, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.Cross(normal, Vector3.right); } Vector3 val2 = Vector3.Cross(((Vector3)(ref val)).normalized, normal); return ((Vector3)(ref val2)).normalized; } private static void RemoveColliders(GameObject gameObject) { Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } } } internal static class ParticleUtility { internal static void SpawnPaintParticles(Vector3 position, Color paintColor, float radius, bool catastrophic) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown GameObject val = new GameObject("ExplosiveSprayPaint_Particles"); val.transform.position = position; ParticleSystem obj = val.AddComponent<ParticleSystem>(); MainModule main = obj.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(paintColor); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(catastrophic ? 1.3f : 0.8f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(catastrophic ? 12f : 6f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(catastrophic ? 0.22f : 0.12f); ((MainModule)(ref main)).maxParticles = (catastrophic ? 450 : 180); ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1; EmissionModule emission = obj.emission; ((EmissionModule)(ref emission)).enabled = false; ShapeModule shape = obj.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.25f; CollisionModule collision = obj.collision; ((CollisionModule)(ref collision)).enabled = true; ((CollisionModule)(ref collision)).type = (ParticleSystemCollisionType)1; ((CollisionModule)(ref collision)).dampen = MinMaxCurve.op_Implicit(0.55f); ((CollisionModule)(ref collision)).bounce = MinMaxCurve.op_Implicit(0.15f); ((CollisionModule)(ref collision)).lifetimeLoss = MinMaxCurve.op_Implicit(0.35f); ParticleSystemRenderer component = ((Component)obj).GetComponent<ParticleSystemRenderer>(); component.renderMode = (ParticleSystemRenderMode)0; ((Renderer)component).material = new Material(Shader.Find("Sprites/Default")); obj.Emit(catastrophic ? 160 : 65); val.AddComponent<TemporaryObject>().Initialize(catastrophic ? 4f : 2.5f, destroyInstancedMaterials: true); } } internal static class SprayPaintIntrospection { private const int TextureSampleSize = 16; private static readonly string[] ColorPropertyNames = new string[4] { "_BaseColor", "_Color", "_TintColor", "_EmissionColor" }; private static readonly string[] TexturePropertyNames = new string[6] { "_BaseColorMap", "_MainTex", "_UnlitColorMap", "_BaseMap", "_DecalColorMap", "_EmissionMap" }; internal static Color GetCurrentSprayColor(SprayPaintItem sprayPaintItem) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00f4: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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) int valueOrDefault = TryReadInt(sprayPaintItem, "sprayCanMatsIndex", "sprayPaintColorIndex", "colorIndex", "materialIndex").GetValueOrDefault(-1); if (TryGetIndexedMaterialColor(sprayPaintItem, valueOrDefault, "particleMats", new string[4] { "particleMats", "sprayParticleMats", "sprayPaintParticleMaterials", "particleMaterials" }, out Color color, out string source)) { return LogResolvedColor(sprayPaintItem, color, valueOrDefault, source); } Color? val = TryReadColor(sprayPaintItem, "sprayPaintColor", "currentColor", "paintColor", "sprayColor"); if (val.HasValue) { return LogResolvedColor(sprayPaintItem, val.Value, valueOrDefault, "direct color field"); } if (TryGetIndexedMaterialColor(sprayPaintItem, valueOrDefault, "sprayCanMats", new string[3] { "sprayCanMats", "sprayPaintMaterials", "sprayCanMaterials" }, out Color color2, out string source2)) { return LogResolvedColor(sprayPaintItem, color2, valueOrDefault, source2); } if (TryGetRendererColor(sprayPaintItem, out Color color3, out string source3)) { return LogResolvedColor(sprayPaintItem, color3, valueOrDefault, source3); } return LogResolvedColor(sprayPaintItem, Color.magenta, valueOrDefault, "fallback magenta"); } internal static T? GetObjectField<T>(object instance, params string[] names) where T : class { Type type = instance.GetType(); foreach (string text in names) { if (AccessTools.Field(type, text)?.GetValue(instance) is T result) { return result; } PropertyInfo propertyInfo = AccessTools.Property(type, text); if ((object)propertyInfo != null && propertyInfo.CanRead && propertyInfo.GetValue(instance) is T result2) { return result2; } } return null; } internal static float? GetFloatField(object instance, params string[] names) { Type type = instance.GetType(); foreach (string text in names) { object obj = AccessTools.Field(type, text)?.GetValue(instance); if (obj is float) { return (float)obj; } PropertyInfo propertyInfo = AccessTools.Property(type, text); object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null); if (obj2 is float) { return (float)obj2; } } return null; } internal static bool? GetBoolField(object instance, params string[] names) { Type type = instance.GetType(); foreach (string text in names) { object obj = AccessTools.Field(type, text)?.GetValue(instance); if (obj is bool) { return (bool)obj; } PropertyInfo propertyInfo = AccessTools.Property(type, text); object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null); if (obj2 is bool) { return (bool)obj2; } } return null; } internal static void DestroySprayCanSafely(SprayPaintItem sprayPaintItem) { try { StopSprayingSafely(sprayPaintItem); if ((Object)(object)((GrabbableObject)sprayPaintItem).playerHeldBy != (Object)null) { MethodInfo methodInfo = AccessTools.Method(((object)sprayPaintItem).GetType(), "DestroyObjectInHand", (Type[])null, (Type[])null); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = ((i == 0) ? ((GrabbableObject)sprayPaintItem).playerHeldBy : (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : GetDefaultValue(parameters[i].ParameterType))); } methodInfo.Invoke(sprayPaintItem, array); return; } } NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject; if ((Object)(object)networkObject != (Object)null && networkObject.IsSpawned) { networkObject.Despawn(true); } else { Object.Destroy((Object)(object)((Component)sprayPaintItem).gameObject); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not destroy ruptured spray can through normal path: " + ex.Message)); try { Object.Destroy((Object)(object)((Component)sprayPaintItem).gameObject); } catch { } } } internal static void StopSprayingSafely(SprayPaintItem sprayPaintItem) { try { AccessTools.Method(((object)sprayPaintItem).GetType(), "StopSpraying", (Type[])null, (Type[])null)?.Invoke(sprayPaintItem, Array.Empty<object>()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not call StopSpraying before rupture cleanup: " + ex.Message)); } TrySetBoolField(sprayPaintItem, false, "isSpraying", "tryingToUseEmptyCan", "makingAudio"); AudioSource objectField = GetObjectField<AudioSource>(sprayPaintItem, new string[1] { "sprayAudio" }); if ((Object)(object)objectField != (Object)null) { objectField.Stop(); } ParticleSystem objectField2 = GetObjectField<ParticleSystem>(sprayPaintItem, new string[2] { "sprayParticle", "sprayCanNeedsShakingParticle" }); if ((Object)(object)objectField2 != (Object)null) { objectField2.Stop(true, (ParticleSystemStopBehavior)0); } } internal static bool TryAddVanillaPaint(SprayPaintItem sprayPaintItem, Vector3 point, Vector3 normal) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0048: 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_005c: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo methodInfo = AccessTools.Method(((object)sprayPaintItem).GetType(), "AddSprayPaintLocal", (Type[])null, (Type[])null); if (methodInfo == null) { return false; } Vector3 val = point + ((Vector3)(ref normal)).normalized * 0.45f; Vector3 val2 = -((Vector3)(ref normal)).normalized; object obj = methodInfo.Invoke(sprayPaintItem, new object[2] { val, val2 }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception ex) { if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)("Vanilla paint placement failed: " + ex.Message)); } return false; } } internal static void AddExternalForce(PlayerControllerB player, Vector3 force) { //IL_003e: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) try { FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerControllerB), "externalForces"); if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(Vector3))) { Vector3 val = (Vector3)fieldInfo.GetValue(player); fieldInfo.SetValue(player, val + force); } } catch { } } private static Color? TryReadColor(object instance, params string[] names) { //IL_0035: 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_003c: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Type type = instance.GetType(); foreach (string text in names) { object obj = AccessTools.Field(type, text)?.GetValue(instance); if (obj is Color) { return (Color)obj; } if (obj is Color32 val) { return Color32.op_Implicit(val); } PropertyInfo propertyInfo = AccessTools.Property(type, text); object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null); if (obj2 is Color) { return (Color)obj2; } if (obj2 is Color32 val2) { return Color32.op_Implicit(val2); } } return null; } private static int? TryReadInt(object instance, params string[] names) { Type type = instance.GetType(); foreach (string text in names) { object obj = AccessTools.Field(type, text)?.GetValue(instance); if (obj is int) { return (int)obj; } PropertyInfo propertyInfo = AccessTools.Property(type, text); object obj2 = (((object)propertyInfo != null && propertyInfo.CanRead) ? propertyInfo.GetValue(instance) : null); if (obj2 is int) { return (int)obj2; } } return null; } private static void TrySetBoolField(object instance, bool value, params string[] names) { Type type = instance.GetType(); foreach (string text in names) { FieldInfo fieldInfo = AccessTools.Field(type, text); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { fieldInfo.SetValue(instance, value); } } } private static bool TryGetIndexedMaterialColor(SprayPaintItem sprayPaintItem, int colorIndex, string fieldLabel, string[] fieldNames, out Color color, out string source) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) color = default(Color); source = string.Empty; Material[] objectField = GetObjectField<Material[]>(sprayPaintItem, fieldNames); if (objectField == null || colorIndex < 0 || colorIndex >= objectField.Length || (Object)(object)objectField[colorIndex] == (Object)null) { return false; } Material val = objectField[colorIndex]; if (!TryResolveMaterialPaintColor(val, out color, out string source2)) { return false; } source = $"{fieldLabel}[{colorIndex}] {source2} ({((Object)val).name})"; return true; } private static bool TryGetRendererColor(SprayPaintItem sprayPaintItem, out Color color, out string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) color = default(Color); source = string.Empty; Renderer[] componentsInChildren = ((Component)sprayPaintItem).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || val.sharedMaterials == null) { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (!((Object)(object)val2 == (Object)null) && TryResolveMaterialPaintColor(val2, out color, out string source2)) { source = "renderer material " + source2 + " (" + ((Object)val2).name + ")"; return true; } } } return false; } private static bool TryResolveMaterialPaintColor(Material material, out Color color, out string source) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (TryAverageMaterialTexture(material, out color, out source)) { return true; } string[] colorPropertyNames = ColorPropertyNames; foreach (string text in colorPropertyNames) { if (!material.HasProperty(text)) { continue; } try { color = NormalizePaintColor(material.GetColor(text)); if (IsUsefulPaintColor(color)) { source = text + " color"; return true; } } catch { } } try { color = NormalizePaintColor(material.color); if (IsUsefulPaintColor(color)) { source = "material.color"; return true; } } catch { } color = default(Color); source = string.Empty; return false; } private static bool TryAverageMaterialTexture(Material material, out Color color, out string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) color = default(Color); source = string.Empty; string[] texturePropertyNames = TexturePropertyNames; foreach (string text in texturePropertyNames) { if (material.HasProperty(text)) { Texture texture; try { texture = material.GetTexture(text); } catch { continue; } if (!((Object)(object)texture == (Object)null) && TryAverageTexture(texture, out color) && IsUsefulPaintColor(color)) { source = text + " texture average"; return true; } } } return false; } private static bool TryAverageTexture(Texture texture, out Color color) { Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (val != null && TryAverageReadableTexture(val, out color)) { return true; } return TryAverageTextureWithRenderTexture(texture, out color); } private static bool TryAverageReadableTexture(Texture2D texture, out Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { return TryAverageReadableTexturePixels(texture, out color); } catch { color = default(Color); return false; } } private static bool TryAverageTextureWithRenderTexture(Texture texture, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) color = default(Color); RenderTexture active = RenderTexture.active; RenderTexture val = null; Texture2D val2 = null; try { val = RenderTexture.GetTemporary(16, 16, 0, (RenderTextureFormat)0); val2 = new Texture2D(16, 16, (TextureFormat)4, false); Graphics.Blit(texture, val); RenderTexture.active = val; val2.ReadPixels(new Rect(0f, 0f, 16f, 16f), 0, 0); val2.Apply(false, false); return TryAverageReadableTexturePixels(val2, out color); } catch { color = default(Color); return false; } finally { RenderTexture.active = active; if ((Object)(object)val != (Object)null) { RenderTexture.ReleaseTemporary(val); } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } } } private static bool TryAverageReadableTexturePixels(Texture2D texture, out Color color) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = 0f; float num3 = 0f; float num4 = 0f; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { Color pixelBilinear = texture.GetPixelBilinear(((float)j + 0.5f) / 16f, ((float)i + 0.5f) / 16f); float num5 = Mathf.Clamp01(pixelBilinear.a); if (!(num5 < 0.08f)) { num2 += pixelBilinear.r * num5; num3 += pixelBilinear.g * num5; num4 += pixelBilinear.b * num5; num += num5; } } } if (num <= 0.001f) { color = default(Color); return false; } color = NormalizePaintColor(new Color(num2 / num, num3 / num, num4 / num, 1f)); return true; } private static Color NormalizePaintColor(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) color.r = Mathf.Clamp01(color.r); color.g = Mathf.Clamp01(color.g); color.b = Mathf.Clamp01(color.b); color.a = ((color.a < 0.2f) ? 1f : Mathf.Clamp01(color.a)); return color; } private static bool IsUsefulPaintColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(color.r, Mathf.Max(color.g, color.b)); float num2 = Mathf.Min(color.r, Mathf.Min(color.g, color.b)); float num3 = ((num <= 0.001f) ? 0f : ((num - num2) / num)); if (num > 0.05f) { if (num > 0.92f) { return !(num3 < 0.08f); } return true; } return false; } private static Color LogResolvedColor(SprayPaintItem sprayPaintItem, Color color, int colorIndex, string source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Color val = NormalizePaintColor(color); if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)("Resolved spray paint color " + ColorUtility.ToHtmlStringRGBA(val) + " from " + source + "; " + string.Format("sprayCanMatsIndex={0}, {1}, {2}.", colorIndex, DescribeSelectedMaterial(sprayPaintItem, "particleMats", colorIndex), DescribeSelectedMaterial(sprayPaintItem, "sprayCanMats", colorIndex)))); } return val; } private static string DescribeSelectedMaterial(SprayPaintItem sprayPaintItem, string fieldName, int colorIndex) { Material[] objectField = GetObjectField<Material[]>(sprayPaintItem, new string[1] { fieldName }); if (objectField == null) { return fieldName + "=missing"; } if (colorIndex < 0 || colorIndex >= objectField.Length) { return $"{fieldName}=index {colorIndex} outside {objectField.Length}"; } Material val = objectField[colorIndex]; if (!((Object)(object)val == (Object)null)) { return $"{fieldName}[{colorIndex}]={((Object)val).name}"; } return $"{fieldName}[{colorIndex}]=null"; } private static object? GetDefaultValue(Type type) { if (!type.IsValueType) { return null; } return Activator.CreateInstance(type); } } internal static class SprayPaintRuntimeWatcher { [CompilerGenerated] private static class <>O { public static LogCallback <0>__OnUnityLogMessageReceived; } private static SprayPaintItem? _lastSprayPaintItem; private static int _lastInstanceId; private static float _lastShakeMeter = -1f; private static bool _lastIsSpraying; private static float _nextDebugLogTime; private static float _lastLogFallbackTriggerTime = -10f; private static bool _registered; internal static void Register() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (!_registered) { object obj = <>O.<0>__OnUnityLogMessageReceived; if (obj == null) { LogCallback val = OnUnityLogMessageReceived; <>O.<0>__OnUnityLogMessageReceived = val; obj = (object)val; } Application.logMessageReceived += (LogCallback)obj; _registered = true; LogDebug("Runtime watcher registered on plugin update loop and Unity log fallback."); } } internal static void Unregister() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (_registered) { object obj = <>O.<0>__OnUnityLogMessageReceived; if (obj == null) { LogCallback val = OnUnityLogMessageReceived; <>O.<0>__OnUnityLogMessageReceived = val; obj = (object)val; } Application.logMessageReceived -= (LogCallback)obj; _registered = false; LogDebug("Runtime watcher unregistered."); } } internal static void Tick() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; SprayPaintItem val2 = SprayPaintItemPatches.FindLocalHeldSprayPaint(); if ((Object)(object)val2 == (Object)null) { ClearHeldItem(); return; } int instanceID = ((Object)val2).GetInstanceID(); float valueOrDefault = SprayPaintIntrospection.GetFloatField(val2, "sprayCanShakeMeter").GetValueOrDefault(-1f); bool valueOrDefault2 = SprayPaintIntrospection.GetBoolField(val2, "isSpraying").GetValueOrDefault(); if ((Object)(object)_lastSprayPaintItem != (Object)(object)val2 || _lastInstanceId != instanceID) { _lastSprayPaintItem = val2; _lastInstanceId = instanceID; _lastShakeMeter = valueOrDefault; _lastIsSpraying = valueOrDefault2; object[] obj = new object[4] { instanceID, null, null, null }; NetworkObject networkObject = ((NetworkBehaviour)val2).NetworkObject; obj[1] = ((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none"; obj[2] = valueOrDefault; obj[3] = valueOrDefault2; LogDebug(string.Format("Runtime watcher tracking held SprayPaintItem. instance={0}, objectId={1}, shakeMeter={2:0.00}, isSpraying={3}.", obj)); return; } if (valueOrDefault >= 0f && _lastShakeMeter >= 0f && valueOrDefault - _lastShakeMeter >= 0.03f) { SprayPaintItemPatches.ReportShake(val2, $"runtime watcher shake meter {_lastShakeMeter:0.00}->{valueOrDefault:0.00}"); } if (Plugin.ModConfig.EnableDebugLogging.Value && Time.unscaledTime >= _nextDebugLogTime) { _nextDebugLogTime = Time.unscaledTime + 5f; object[] obj2 = new object[5] { instanceID, null, null, null, null }; NetworkObject networkObject2 = ((NetworkBehaviour)val2).NetworkObject; obj2[1] = ((networkObject2 != null) ? networkObject2.NetworkObjectId.ToString() : null) ?? "none"; obj2[2] = valueOrDefault; obj2[3] = valueOrDefault2; obj2[4] = (Object)(object)((GrabbableObject)val2).playerHeldBy == (Object)(object)val; LogDebug(string.Format("Runtime watcher heartbeat. instance={0}, objectId={1}, shakeMeter={2:0.00}, isSpraying={3}, heldByLocal={4}.", obj2)); } _lastShakeMeter = valueOrDefault; _lastIsSpraying = valueOrDefault2; } private static void OnUnityLogMessageReceived(string condition, string stackTrace, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)type == 3 && (condition.StartsWith("interact False") || condition == "secondary use G") && !(Time.unscaledTime - _lastLogFallbackTriggerTime < 0.25f)) { _lastLogFallbackTriggerTime = Time.unscaledTime; SprayPaintItem val = SprayPaintItemPatches.FindLocalHeldSprayPaint(); if ((Object)(object)val == (Object)null) { LogDebug("Unity log fallback saw '" + condition + "', but could not find a locally held SprayPaintItem."); } else { SprayPaintItemPatches.ReportShake(val, "Unity log fallback '" + condition + "'"); } } } private static void ClearHeldItem() { if ((Object)(object)_lastSprayPaintItem != (Object)null) { LogDebug("Runtime watcher stopped tracking SprayPaintItem because the local player is no longer holding one."); } _lastSprayPaintItem = null; _lastInstanceId = 0; _lastShakeMeter = -1f; _lastIsSpraying = false; } private static void LogDebug(string message) { if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)message); } } } internal sealed class TemporaryObject : MonoBehaviour { private bool _destroyInstancedMaterials; internal void Initialize(float lifetimeSeconds, bool destroyInstancedMaterials) { _destroyInstancedMaterials = destroyInstancedMaterials; ((MonoBehaviour)this).StartCoroutine(DestroyAfterDelay(lifetimeSeconds)); } private IEnumerator DestroyAfterDelay(float lifetimeSeconds) { yield return (object)new WaitForSeconds(lifetimeSeconds); if ((Object)(object)this != (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void OnDestroy() { if (!_destroyInstancedMaterials) { return; } Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val.material != (Object)null) { Texture mainTexture = val.material.mainTexture; if ((Object)(object)mainTexture != (Object)null && ((Object)mainTexture).name.StartsWith("ExplosiveSprayPaint_")) { Object.Destroy((Object)(object)mainTexture); } Object.Destroy((Object)(object)val.material); } } DecalProjector[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<DecalProjector>(); foreach (DecalProjector val2 in componentsInChildren2) { if ((Object)(object)val2.material != (Object)null) { Object.Destroy((Object)(object)val2.material); } } } } } namespace ExplosiveSprayPaint.Patches { internal static class NetworkLifecyclePatches { [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void RegisterMessagesAfterConnect() { SprayCanExplosionNetworking.Register(); } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void ClearRoundStateOnStart() { ExplosionState.Reset(); } } internal static class SprayPaintItemPatches { internal const float ShakeMeterIncreaseThreshold = 0.03f; internal static void Apply(Harmony harmony) { Patch(harmony, "ItemInteractLeftRight", null, "DetectShake"); Patch(harmony, "ItemActivate", null, "DetectOptionalSprayUse"); Patch(harmony, "LateUpdate", "CaptureShakeMeterBeforeLateUpdate", "DetectShakeMeterIncrease"); Patch(harmony, "Start", null, "LogSprayPaintStart"); Patch(harmony, typeof(PlayerControllerB), "Update", null, "TickRuntimeWatcherFromPlayerUpdate"); } private static void Patch(Harmony harmony, string originalName, string? prefixName = null, string? postfixName = null) { Patch(harmony, typeof(SprayPaintItem), originalName, prefixName, postfixName); } private static void Patch(Harmony harmony, Type originalType, string originalName, string? prefixName = null, string? postfixName = null) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogError((object)("Could not find " + originalType.Name + "." + originalName + "; this mod cannot detect that action.")); return; } HarmonyMethod val = ((prefixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(SprayPaintItemPatches), prefixName, (Type[])null, (Type[])null))); HarmonyMethod val2 = ((postfixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(SprayPaintItemPatches), postfixName, (Type[])null, (Type[])null))); harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); int num = patchInfo?.Prefixes.Count((Patch patch) => patch.owner == "huntedbyacreature.explosivespraypaint") ?? 0; int num2 = patchInfo?.Postfixes.Count((Patch patch) => patch.owner == "huntedbyacreature.explosivespraypaint") ?? 0; Plugin.Log.LogInfo((object)$"Patch check: {originalType.Name}.{originalName} prefixes={num}, postfixes={num2}."); } private static void DetectShake(SprayPaintItem __instance, bool right) { if (!right) { ReportShake(__instance, "ItemInteractLeftRight(false)"); } } private static void DetectOptionalSprayUse(SprayPaintItem __instance, bool used, bool buttonDown) { LogDebug($"ItemActivate observed. used={used}, buttonDown={buttonDown}; spraying is safe and does not roll explosions."); } private static void CaptureShakeMeterBeforeLateUpdate(SprayPaintItem __instance, out float __state) { __state = SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter").GetValueOrDefault(-1f); } private static void DetectShakeMeterIncrease(SprayPaintItem __instance, float __state) { if (!(__state < 0f)) { float valueOrDefault = SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter").GetValueOrDefault(__state); if (valueOrDefault - __state >= 0.03f) { ReportShake(__instance, $"sprayCanShakeMeter increased {__state:0.00}->{valueOrDefault:0.00}"); } } } private static void LogSprayPaintStart(SprayPaintItem __instance) { NetworkObject networkObject = ((NetworkBehaviour)__instance).NetworkObject; LogDebug("SprayPaintItem started. objectId=" + (((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none") + ", shakeMeter=" + (SprayPaintIntrospection.GetFloatField(__instance, "sprayCanShakeMeter")?.ToString("0.00") ?? "unknown")); } private static void TickRuntimeWatcherFromPlayerUpdate() { SprayPaintRuntimeWatcher.Tick(); } internal static void ReportShake(SprayPaintItem sprayPaintItem, string source) { if ((Object)(object)sprayPaintItem == (Object)null || (Object)(object)((GrabbableObject)sprayPaintItem).playerHeldBy == (Object)null) { LogDebug("Ignoring " + source + " because the spray can is not held."); return; } if (SprayPaintIntrospection.GetBoolField(sprayPaintItem, "isSpraying").GetValueOrDefault()) { LogDebug("Ignoring " + source + " because the can is actively spraying. Spraying paint is safe; only shaking can rupture it."); return; } if (!IsHeldByLocalPlayer(((GrabbableObject)sprayPaintItem).playerHeldBy)) { object arg = ((GrabbableObject)sprayPaintItem).playerHeldBy.actualClientId; NetworkManager singleton = NetworkManager.Singleton; LogDebug(string.Format("Ignoring {0} because the holder is not the local player. holder={1}, local={2}.", source, arg, ((singleton != null) ? singleton.LocalClientId.ToString() : null) ?? "none")); return; } string[] obj = new string[6] { "Detected local spray can shake via ", source, ". holder=", ((GrabbableObject)sprayPaintItem).playerHeldBy.playerUsername, ", objectId=", null }; NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject; obj[5] = ((networkObject != null) ? networkObject.NetworkObjectId.ToString() : null) ?? "none"; LogDebug(string.Concat(obj)); SprayCanExplosionNetworking.ReportLocalShake(sprayPaintItem); } internal static SprayPaintItem? FindLocalHeldSprayPaint() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return null; } GrabbableObject currentlyHeldObjectServer = val.currentlyHeldObjectServer; SprayPaintItem val2 = (SprayPaintItem)(object)((currentlyHeldObjectServer is SprayPaintItem) ? currentlyHeldObjectServer : null); if (val2 != null) { return val2; } SprayPaintItem[] array = Object.FindObjectsOfType<SprayPaintItem>(); foreach (SprayPaintItem val3 in array) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((GrabbableObject)val3).playerHeldBy == (Object)null) && ((Object)(object)((GrabbableObject)val3).playerHeldBy == (Object)(object)val || IsHeldByLocalPlayer(((GrabbableObject)val3).playerHeldBy))) { return val3; } } return null; } internal static bool IsHeldByLocalPlayer(PlayerControllerB holder) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)holder == (Object)(object)val) { return true; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsListening) { return holder.actualClientId == singleton.LocalClientId; } return ((NetworkBehaviour)holder).IsOwner; } internal static void LogDebug(string message) { if (Plugin.ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)message); } } } } namespace ExplosiveSprayPaint.Networking { internal readonly struct ExplosionMessage { internal readonly ulong SprayCanNetworkObjectId; internal readonly ulong HolderClientId; internal readonly Vector3 Position; internal readonly Color PaintColor; internal readonly bool Catastrophic; internal readonly int RandomSeed; internal readonly float BlastRadius; internal readonly float PhysicsForce; internal readonly float PaintRadius; internal readonly int PaintCount; internal ExplosionMessage(ulong sprayCanNetworkObjectId, ulong holderClientId, Vector3 position, Color paintColor, bool catastrophic, int randomSeed, float blastRadius, float physicsForce, float paintRadius, int paintCount) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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) SprayCanNetworkObjectId = sprayCanNetworkObjectId; HolderClientId = holderClientId; Position = position; PaintColor = paintColor; Catastrophic = catastrophic; RandomSeed = randomSeed; BlastRadius = blastRadius; PhysicsForce = physicsForce; PaintRadius = paintRadius; PaintCount = paintCount; } internal void Write(FastBufferWriter writer) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref SprayCanNetworkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref HolderClientId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.x, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.y, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref Position.z, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.r, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.g, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.b, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintColor.a, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<bool>(ref Catastrophic, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref RandomSeed, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref BlastRadius, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PhysicsForce, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref PaintRadius, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref PaintCount, default(ForPrimitives)); } internal static bool TryRead(FastBufferReader reader, out ExplosionMessage message) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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_0138: Unknown result type (might be due to invalid IL or missing references) message = default(ExplosionMessage); try { ulong sprayCanNetworkObjectId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref sprayCanNetworkObjectId, default(ForPrimitives)); ulong holderClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref holderClientId, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num3, default(ForPrimitives)); float num4 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num4, default(ForPrimitives)); float num5 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num5, default(ForPrimitives)); float num6 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num6, default(ForPrimitives)); float num7 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num7, default(ForPrimitives)); bool catastrophic = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref catastrophic, default(ForPrimitives)); int randomSeed = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref randomSeed, default(ForPrimitives)); float blastRadius = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref blastRadius, default(ForPrimitives)); float physicsForce = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref physicsForce, default(ForPrimitives)); float paintRadius = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref paintRadius, default(ForPrimitives)); int paintCount = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref paintCount, default(ForPrimitives)); message = new ExplosionMessage(sprayCanNetworkObjectId, holderClientId, new Vector3(num, num2, num3), new Color(num4, num5, num6, num7), catastrophic, randomSeed, blastRadius, physicsForce, paintRadius, paintCount); return true; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"Failed to read explosion message: {arg}"); return false; } } } internal static class ExplosionState { private static readonly HashSet<ulong> ExplodedNetworkObjects = new HashSet<ulong>(); private static readonly Dictionary<ulong, int> LastShakeRequestFrame = new Dictionary<ulong, int>(); internal static bool HasExploded(ulong networkObjectId) { lock (ExplodedNetworkObjects) { return ExplodedNetworkObjects.Contains(networkObjectId); } } internal static bool TryMarkExploded(ulong networkObjectId) { lock (ExplodedNetworkObjects) { return ExplodedNetworkObjects.Add(networkObjectId); } } internal static bool TryMarkShakeRequestThisFrame(ulong networkObjectId, int frame) { lock (LastShakeRequestFrame) { if (LastShakeRequestFrame.TryGetValue(networkObjectId, out var value) && value == frame) { return false; } LastShakeRequestFrame[networkObjectId] = frame; return true; } } internal static void Reset() { lock (ExplodedNetworkObjects) { ExplodedNetworkObjects.Clear(); } lock (LastShakeRequestFrame) { LastShakeRequestFrame.Clear(); } } } internal static class SprayCanExplosionNetworking { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnShakeRequestReceived; public static HandleNamedMessageDelegate <1>__OnExplosionReceived; } private const string ShakeRequestMessage = "huntedbyacreature.explosivespraypaint.ShakeRequest"; private const string ExplosionMessageName = "huntedbyacreature.explosivespraypaint.Explosion"; private static bool _registered; internal static void Register() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (!_registered && ((singleton != null) ? singleton.CustomMessagingManager : null) != null) { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnShakeRequestReceived; if (obj == null) { HandleNamedMessageDelegate val = OnShakeRequestReceived; <>O.<0>__OnShakeRequestReceived = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.ShakeRequest", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnExplosionReceived; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnExplosionReceived; <>O.<1>__OnExplosionReceived = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.Explosion", (HandleNamedMessageDelegate)obj2); _registered = true; } } internal static void Unregister() { NetworkManager singleton = NetworkManager.Singleton; if (_registered && ((singleton != null) ? singleton.CustomMessagingManager : null) != null) { singleton.CustomMessagingManager.UnregisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.ShakeRequest"); singleton.CustomMessagingManager.UnregisterNamedMessageHandler("huntedbyacreature.explosivespraypaint.Explosion"); _registered = false; } } internal static void ReportLocalShake(SprayPaintItem sprayPaintItem) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) Register(); NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject; if ((Object)(object)networkObject == (Object)null || ExplosionState.HasExploded(networkObject.NetworkObjectId)) { LogDebug(((Object)(object)networkObject == (Object)null) ? "Shake ignored because the spray can has no NetworkObject." : $"Shake ignored because spray can {networkObject.NetworkObjectId} already exploded."); return; } if (!ExplosionState.TryMarkShakeRequestThisFrame(networkObject.NetworkObjectId, Time.frameCount)) { LogDebug($"Duplicate shake request ignored for frame {Time.frameCount}, object {networkObject.NetworkObjectId}."); return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening) { LogDebug("Shake detected, but NetworkManager is not listening yet."); return; } if (singleton.IsServer) { LogDebug($"Processing shake locally on host for object {networkObject.NetworkObjectId}."); TryProcessShakeOnServer(sprayPaintItem, singleton.LocalClientId); return; } LogDebug($"Sending shake request to host for object {networkObject.NetworkObjectId}."); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ulong networkObjectId = networkObject.NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("huntedbyacreature.explosivespraypaint.ShakeRequest", 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void OnShakeRequestReceived(ulong senderClientId, FastBufferReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer) { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives)); LogDebug($"Host received shake request from client {senderClientId} for object {num}."); SprayPaintItem sprayPaintItem = default(SprayPaintItem); if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(num, out var value)) { LogDebug($"Host could not find spawned object {num}."); } else if (!((Component)value).TryGetComponent<SprayPaintItem>(ref sprayPaintItem)) { LogDebug($"Host object {num} is not a SprayPaintItem."); } else { TryProcessShakeOnServer(sprayPaintItem, senderClientId); } } } private static void TryProcessShakeOnServer(SprayPaintItem sprayPaintItem, ulong senderClientId) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) NetworkObject networkObject = ((NetworkBehaviour)sprayPaintItem).NetworkObject; if ((Object)(object)networkObject == (Object)null || ExplosionState.HasExploded(networkObject.NetworkObjectId)) { LogDebug(((Object)(object)networkObject == (Object)null) ? "Host ignored shake because the spray can has no NetworkObject." : $"Host ignored shake because object {networkObject.NetworkObjectId}