using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Dissonance.Integrations.Unity_NFGO;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.AI.Navigation;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace V81ErrorFix
{
internal static class NullRefGuard
{
private const int MaxWarningsPerKey = 5;
private static readonly Dictionary<string, int> WarningCounts = new Dictionary<string, int>();
internal static Exception Suppress(Exception exception, string key)
{
if (!(exception is NullReferenceException))
{
return exception;
}
WarningCounts.TryGetValue(key, out var value);
if (value < 5)
{
value++;
WarningCounts[key] = value;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"Suppressed NullReferenceException in {key} ({value}/{5}); the object will safely retry on later updates.");
}
}
return null;
}
}
internal sealed class ParticleMeshShapeGuard : MonoBehaviour
{
private sealed class ParticleMeshWarningBatch
{
internal readonly string MeshName;
internal readonly string Reason;
internal readonly HashSet<string> ParticleSystemNames = new HashSet<string>();
internal ParticleMeshWarningBatch(string meshName, string reason)
{
MeshName = meshName;
Reason = reason;
}
}
private sealed class CachedMeshInspection
{
internal readonly Mesh Mesh;
internal readonly string InvalidReason;
internal CachedMeshInspection(Mesh mesh, string invalidReason)
{
Mesh = mesh;
InvalidReason = invalidReason;
}
}
private const float ScanInterval = 5f;
private const int ScanBatchSize = 64;
private const int MeshInspectionCacheCleanupThreshold = 256;
private float _nextScanTime;
private ParticleSystem[] _scanQueue;
private int _scanIndex;
private readonly HashSet<int> _patchedParticleSystems = new HashSet<int>();
private readonly WarningLimiter _warnings = new WarningLimiter();
private readonly Dictionary<string, ParticleMeshWarningBatch> _pendingWarnings = new Dictionary<string, ParticleMeshWarningBatch>();
private readonly Dictionary<int, CachedMeshInspection> _meshInspectionCache = new Dictionary<int, CachedMeshInspection>();
internal static void EnsureCreated()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
if (!((Object)(object)Object.FindObjectOfType<ParticleMeshShapeGuard>() != (Object)null))
{
GameObject val = new GameObject("V81ErrorFix.ParticleMeshShapeGuard");
Object.DontDestroyOnLoad((Object)(object)val);
((Object)val).hideFlags = (HideFlags)61;
val.AddComponent<ParticleMeshShapeGuard>();
}
}
private void Update()
{
if (_scanQueue != null)
{
ContinueParticleSystemScan();
}
else if (!(Time.realtimeSinceStartup < _nextScanTime))
{
_nextScanTime = Time.realtimeSinceStartup + 5f;
BeginParticleSystemScan();
ContinueParticleSystemScan();
}
}
private void BeginParticleSystemScan()
{
_pendingWarnings.Clear();
_scanQueue = Object.FindObjectsOfType<ParticleSystem>(true);
_scanIndex = 0;
}
private void ContinueParticleSystemScan()
{
if (_scanQueue != null)
{
int num = Math.Min(_scanIndex + 64, _scanQueue.Length);
while (_scanIndex < num)
{
TryPatchParticleSystem(_scanQueue[_scanIndex]);
_scanIndex++;
}
if (_scanIndex >= _scanQueue.Length)
{
_scanQueue = null;
_scanIndex = 0;
FlushParticleMeshWarnings();
}
}
}
private void TryPatchParticleSystem(ParticleSystem particleSystem)
{
//IL_0032: 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)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)particleSystem == (Object)null)
{
return;
}
int instanceID = ((Object)particleSystem).GetInstanceID();
if (_patchedParticleSystems.Contains(instanceID))
{
return;
}
try
{
ShapeModule shape = particleSystem.shape;
if (((ShapeModule)(ref shape)).enabled && TryGetShapeMesh(shape, out var mesh) && !((Object)(object)mesh == (Object)null))
{
string invalidMeshReasonCached = GetInvalidMeshReasonCached(mesh);
if (invalidMeshReasonCached != null)
{
((ShapeModule)(ref shape)).enabled = false;
_patchedParticleSystems.Add(instanceID);
QueueParticleMeshWarning(((Object)mesh).name, invalidMeshReasonCached, ((Object)particleSystem).name);
}
}
}
catch (Exception ex)
{
_patchedParticleSystems.Add(instanceID);
QueueParticleMeshWarning("inspection", "could not be inspected safely: " + ex.GetType().Name, ((Object)particleSystem).name);
}
}
private void QueueParticleMeshWarning(string meshName, string reason, string particleSystemName)
{
string key = meshName + "|" + reason;
if (_warnings.CanWarn(key))
{
if (!_pendingWarnings.TryGetValue(key, out var value))
{
value = new ParticleMeshWarningBatch(meshName, reason);
_pendingWarnings[key] = value;
}
value.ParticleSystemNames.Add(particleSystemName);
}
}
private void FlushParticleMeshWarnings()
{
foreach (KeyValuePair<string, ParticleMeshWarningBatch> pendingWarning in _pendingWarnings)
{
ParticleMeshWarningBatch warningBatch = pendingWarning.Value;
_warnings.Warn(pendingWarning.Key, delegate
{
string text = string.Join(", ", warningBatch.ParticleSystemNames);
return "Disabled mesh shape because mesh '" + warningBatch.MeshName + "' " + warningBatch.Reason + " on particle systems: " + text + ".";
});
}
}
private string GetInvalidMeshReasonCached(Mesh mesh)
{
int instanceID = ((Object)mesh).GetInstanceID();
if (_meshInspectionCache.TryGetValue(instanceID, out var value) && (Object)(object)value.Mesh == (Object)(object)mesh)
{
return value.InvalidReason;
}
string invalidMeshReason = GetInvalidMeshReason(mesh);
_meshInspectionCache[instanceID] = new CachedMeshInspection(mesh, invalidMeshReason);
CleanupMeshInspectionCacheIfNeeded();
return invalidMeshReason;
}
private void CleanupMeshInspectionCacheIfNeeded()
{
if (_meshInspectionCache.Count < 256)
{
return;
}
List<int> list = null;
foreach (KeyValuePair<int, CachedMeshInspection> item in _meshInspectionCache)
{
if (!((Object)(object)item.Value.Mesh != (Object)null))
{
if (list == null)
{
list = new List<int>();
}
list.Add(item.Key);
}
}
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
_meshInspectionCache.Remove(list[i]);
}
}
}
private static bool TryGetShapeMesh(ShapeModule shape, out Mesh mesh)
{
//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_000c: 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_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Invalid comparison between Unknown and I4
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
mesh = null;
ParticleSystemShapeType shapeType = ((ShapeModule)(ref shape)).shapeType;
ParticleSystemShapeType val = shapeType;
if ((int)val != 6)
{
if ((int)val != 13)
{
if ((int)val == 14)
{
mesh = (((Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer != (Object)null) ? ((ShapeModule)(ref shape)).skinnedMeshRenderer.sharedMesh : null);
return (Object)(object)mesh != (Object)null;
}
return false;
}
object obj;
if (!((Object)(object)((ShapeModule)(ref shape)).meshRenderer != (Object)null))
{
obj = null;
}
else
{
MeshFilter component = ((Component)((ShapeModule)(ref shape)).meshRenderer).GetComponent<MeshFilter>();
obj = ((component != null) ? component.sharedMesh : null);
}
mesh = (Mesh)obj;
return (Object)(object)mesh != (Object)null;
}
mesh = ((ShapeModule)(ref shape)).mesh;
return (Object)(object)mesh != (Object)null;
}
private static string GetInvalidMeshReason(Mesh mesh)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: 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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
if (!mesh.isReadable)
{
return "is not readable";
}
try
{
Vector3[] vertices = mesh.vertices;
int[] triangles = mesh.triangles;
if (vertices == null || triangles == null || vertices.Length == 0 || triangles.Length < 3)
{
return "has zero surface area";
}
double num = 0.0;
for (int i = 0; i + 2 < triangles.Length; i += 3)
{
Vector3 val = vertices[triangles[i]];
Vector3 val2 = vertices[triangles[i + 1]];
Vector3 val3 = vertices[triangles[i + 2]];
double num2 = num;
Vector3 val4 = Vector3.Cross(val2 - val, val3 - val);
num = num2 + (double)((Vector3)(ref val4)).magnitude * 0.5;
if (num > 0.0001)
{
return null;
}
}
}
catch
{
return "could not be inspected safely";
}
return "has zero surface area";
}
}
internal sealed class WarningLimiter
{
private readonly int _maxWarnings;
private readonly Dictionary<string, int> _warningCounts = new Dictionary<string, int>();
internal WarningLimiter(int maxWarnings = 5)
{
_maxWarnings = maxWarnings;
}
internal void Warn(string key, string message)
{
if (TryIncrement(key, out var warningCount))
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({warningCount}/{_maxWarnings})");
}
}
}
internal void Warn(string key, Func<string> messageFactory)
{
if (TryIncrement(key, out var warningCount))
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{messageFactory()} ({warningCount}/{_maxWarnings})");
}
}
}
internal bool CanWarn(string key)
{
_warningCounts.TryGetValue(key, out var value);
return value < _maxWarnings;
}
private bool TryIncrement(string key, out int warningCount)
{
_warningCounts.TryGetValue(key, out warningCount);
if (warningCount >= _maxWarnings)
{
return false;
}
warningCount++;
_warningCounts[key] = warningCount;
return true;
}
}
[HarmonyPatch]
internal static class DisabledAudioSourcePlayGuardPatch
{
[CompilerGenerated]
private sealed class <TargetMethods>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
private MethodInfo[] <>s__1;
private int <>s__2;
private MethodInfo <method>5__3;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>s__1 = null;
<method>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
goto IL_00a4;
}
<>1__state = -1;
<>s__1 = typeof(AudioSource).GetMethods(BindingFlags.Instance | BindingFlags.Public);
<>s__2 = 0;
goto IL_00ba;
IL_00a4:
<method>5__3 = null;
<>s__2++;
goto IL_00ba;
IL_00ba:
if (<>s__2 < <>s__1.Length)
{
<method>5__3 = <>s__1[<>s__2];
if (<method>5__3.DeclaringType == typeof(AudioSource) && IsPlaybackMethod(<method>5__3))
{
<>2__current = <method>5__3;
<>1__state = 1;
return true;
}
goto IL_00a4;
}
<>s__1 = null;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__2(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static readonly WarningLimiter GuardFailureWarnings = new WarningLimiter();
[IteratorStateMachine(typeof(<TargetMethods>d__2))]
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__2(-2);
}
private static bool Prefix(AudioSource __instance, MethodBase __originalMethod)
{
try
{
return ShouldAllowPlayback(__instance, __originalMethod);
}
catch (Exception ex)
{
GuardFailureWarnings.Warn("guard-failure", "Disabled AudioSource guard failed safely and allowed original playback: " + ex.GetType().Name + ".");
return true;
}
}
private static bool ShouldAllowPlayback(AudioSource audioSource, MethodBase originalMethod)
{
if ((Object)(object)audioSource == (Object)null || ((Behaviour)audioSource).isActiveAndEnabled)
{
return true;
}
string methodName = originalMethod?.Name ?? "Play";
string key = $"{((Object)audioSource).GetInstanceID()}|{methodName}";
Warnings.Warn(key, delegate
{
string transformPath = GetTransformPath(((Component)audioSource).transform);
return $"Suppressed disabled AudioSource {methodName} on '{transformPath}' because AudioSource.enabled={((Behaviour)audioSource).enabled}, activeInHierarchy={(Object)(object)((Component)audioSource).gameObject != (Object)null && ((Component)audioSource).gameObject.activeInHierarchy}.";
});
return false;
}
private static bool IsPlaybackMethod(MethodInfo method)
{
return method.ReturnType == typeof(void) && (method.Name == "Play" || method.Name == "PlayDelayed" || method.Name == "PlayScheduled" || method.Name == "PlayOneShot");
}
internal static string GetTransformPath(Transform transform)
{
if ((Object)(object)transform == (Object)null)
{
return "unknown";
}
string text = ((Object)transform).name;
Transform parent = transform.parent;
while ((Object)(object)parent != (Object)null)
{
text = ((Object)parent).name + "/" + text;
parent = parent.parent;
}
return text;
}
}
[HarmonyPatch]
internal static class AudioSourcePlayOneShotNullClipGuardPatch
{
[CompilerGenerated]
private sealed class <TargetMethods>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(AudioSource), "PlayOneShot", new Type[1] { typeof(AudioClip) }, (Type[])null);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(AudioSource), "PlayOneShot", new Type[2]
{
typeof(AudioClip),
typeof(float)
}, (Type[])null);
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__2(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static readonly WarningLimiter GuardFailureWarnings = new WarningLimiter();
[IteratorStateMachine(typeof(<TargetMethods>d__2))]
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__2(-2);
}
private static bool Prefix(AudioSource __instance, AudioClip __0)
{
try
{
if ((Object)(object)__0 != (Object)null)
{
return true;
}
WarnNullClip(__instance);
return false;
}
catch (Exception ex)
{
GuardFailureWarnings.Warn("guard-failure", "AudioSource null AudioClip guard failed safely and allowed original PlayOneShot: " + ex.GetType().Name + ".");
return true;
}
}
private static void WarnNullClip(AudioSource audioSource)
{
string key = (((Object)(object)audioSource != (Object)null) ? $"null-clip|{((Object)audioSource).GetInstanceID()}" : "null-clip|unknown");
Warnings.Warn(key, delegate
{
string text = (((Object)(object)audioSource != (Object)null) ? DisabledAudioSourcePlayGuardPatch.GetTransformPath(((Component)audioSource).transform) : "unknown");
return "Suppressed AudioSource.PlayOneShot on '" + text + "' because AudioClip was null.";
});
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "Update")]
internal static class BushWolfEnemyUpdatePatch
{
private static bool Prefix(BushWolfEnemy __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
return false;
}
if ((Object)(object)((EnemyAI)__instance).agent == (Object)null || (Object)(object)((EnemyAI)__instance).creatureAnimator == (Object)null || (Object)(object)__instance.animationContainer == (Object)null)
{
return false;
}
return true;
}
private static Exception Finalizer(BushWolfEnemy __instance, Exception __exception)
{
if (__exception is NullReferenceException)
{
try
{
if ((Object)(object)__instance != (Object)null)
{
((EnemyAI)__instance).targetPlayer = null;
((EnemyAI)__instance).movingTowardsTargetPlayer = false;
}
}
catch
{
}
}
return NullRefGuard.Suppress(__exception, "BushWolfEnemy.Update");
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "LateUpdate")]
internal static class BushWolfEnemyLateUpdatePatch
{
private static bool Prefix(BushWolfEnemy __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
return false;
}
if ((Object)(object)__instance.tongue == (Object)null || (Object)(object)__instance.tongueStartPoint == (Object)null || (Object)(object)__instance.animationContainer == (Object)null || (Object)(object)__instance.bendHeadBack == (Object)null || __instance.proceduralBodyTargets == null || __instance.IKTargetContainers == null || __instance.IKTargetContainers.Length < __instance.proceduralBodyTargets.Length)
{
return false;
}
return true;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "BushWolfEnemy.LateUpdate");
}
}
[HarmonyPatch(typeof(DocileLocustBeesAI), "Update")]
internal static class DocileLocustBeesAIUpdatePatch
{
private static bool Prefix(DocileLocustBeesAI __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.activeCamera == (Object)null || (Object)(object)__instance.bugsEffect == (Object)null || (Object)(object)((EnemyAI)__instance).creatureVoice == (Object)null || (Object)(object)__instance.scanNode == (Object)null)
{
return false;
}
if (((EnemyAI)__instance).currentBehaviourStateIndex == 1 && ((Object)(object)((EnemyAI)__instance).creatureSFX == (Object)null || (Object)(object)((EnemyAI)__instance).enemyType == (Object)null || ((EnemyAI)__instance).enemyType.audioClips == null || ((EnemyAI)__instance).enemyType.audioClips.Length == 0 || (Object)(object)RoundManager.Instance == (Object)null))
{
return false;
}
return true;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "DocileLocustBeesAI.Update");
}
}
[HarmonyPatch(typeof(CrawlerAI), "Update")]
internal static class CrawlerAIUpdatePatch
{
private static bool Prefix(CrawlerAI __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
return false;
}
if ((Object)(object)((EnemyAI)__instance).agent == (Object)null || (Object)(object)((EnemyAI)__instance).creatureAnimator == (Object)null || (Object)(object)((Component)__instance).transform == (Object)null || __instance.searchForPlayers == null)
{
return false;
}
return true;
}
private static Exception Finalizer(CrawlerAI __instance, Exception __exception)
{
if (__exception is NullReferenceException && (Object)(object)__instance != (Object)null)
{
try
{
((EnemyAI)__instance).movingTowardsTargetPlayer = false;
}
catch
{
}
}
return NullRefGuard.Suppress(__exception, "CrawlerAI.Update");
}
}
[HarmonyPatch(typeof(EntranceTeleport), "Update")]
internal static class EntranceTeleportUpdatePatch
{
private static readonly FieldInfo TriggerScriptField = AccessTools.Field(typeof(EntranceTeleport), "triggerScript");
private static readonly FieldInfo CheckForEnemiesIntervalField = AccessTools.Field(typeof(EntranceTeleport), "checkForEnemiesInterval");
private static readonly FieldInfo EnemyNearLastCheckField = AccessTools.Field(typeof(EntranceTeleport), "enemyNearLastCheck");
private static readonly FieldInfo GotExitPointField = AccessTools.Field(typeof(EntranceTeleport), "gotExitPoint");
private static bool Prefix(EntranceTeleport __instance)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null)
{
return false;
}
if (!__instance.isEntranceToBuilding)
{
return false;
}
if ((Object)(object)RoundManager.Instance == (Object)null)
{
return false;
}
InteractTrigger val = (InteractTrigger)TriggerScriptField.GetValue(__instance);
if ((Object)(object)val == (Object)null)
{
return false;
}
float num = (float)CheckForEnemiesIntervalField.GetValue(__instance);
if (num > 0f)
{
CheckForEnemiesIntervalField.SetValue(__instance, num - Time.deltaTime);
return false;
}
if (!(bool)GotExitPointField.GetValue(__instance))
{
if (__instance.FindExitPoint())
{
GotExitPointField.SetValue(__instance, true);
}
return false;
}
if (((Object)(object)__instance.exitScript == (Object)null || (Object)(object)__instance.exitScript.entrancePoint == (Object)null) && !__instance.FindExitPoint())
{
return false;
}
CheckForEnemiesIntervalField.SetValue(__instance, 1f);
bool flag = false;
if (RoundManager.Instance.SpawnedEnemies != null)
{
foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies)
{
if (!((Object)(object)spawnedEnemy == (Object)null) && !((Object)(object)((Component)spawnedEnemy).transform == (Object)null) && !spawnedEnemy.isEnemyDead)
{
if ((Object)(object)__instance.exitScript == (Object)null || (Object)(object)__instance.exitScript.entrancePoint == (Object)null)
{
break;
}
if (Vector3.Distance(((Component)spawnedEnemy).transform.position, __instance.exitScript.entrancePoint.position) < 7.7f)
{
flag = true;
break;
}
}
}
}
bool flag2 = (bool)EnemyNearLastCheckField.GetValue(__instance);
if (flag && !flag2)
{
EnemyNearLastCheckField.SetValue(__instance, true);
val.hoverTip = "[Near activity detected!]";
}
else if (!flag && flag2)
{
EnemyNearLastCheckField.SetValue(__instance, false);
val.hoverTip = "Enter: [LMB]";
}
return false;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "EntranceTeleport.Update");
}
}
[HarmonyPatch(typeof(RoundManager), "FindMainEntrancePosition")]
internal static class RoundManagerFindMainEntrancePositionPatch
{
private const int MaxWarnings = 5;
private static int _warningCount;
private static bool Prefix(bool getTeleportPosition, bool getOutsideEntrance, ref Vector3 __result)
{
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: 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_00ac: 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_0072: Unknown result type (might be due to invalid IL or missing references)
EntranceTeleport[] array = Object.FindObjectsOfType<EntranceTeleport>(false);
EntranceTeleport val = null;
EntranceTeleport val2 = null;
foreach (EntranceTeleport val3 in array)
{
if (!((Object)(object)val3 == (Object)null))
{
if (val == null)
{
val = val3;
}
if (val3.entranceId == 0 && val2 == null)
{
val2 = val3;
}
if (val3.entranceId == 0 && val3.isEntranceToBuilding == getOutsideEntrance)
{
__result = GetEntrancePosition(val3, getTeleportPosition);
return false;
}
}
}
EntranceTeleport val4 = val2 ?? val;
if ((Object)(object)val4 != (Object)null)
{
__result = GetEntrancePosition(val4, getTeleportPosition);
Warn("Main entrance position was missing; using the first available EntranceTeleport instead of origin.");
return false;
}
__result = Vector3.zero;
if (!IsCompanyLevel())
{
Warn("Main entrance position was missing and no EntranceTeleport fallback existed; returning origin.");
}
return false;
}
private static Vector3 GetEntrancePosition(EntranceTeleport entrance, bool getTeleportPosition)
{
//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_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: 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)
//IL_0055: 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_005a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)entrance == (Object)null)
{
return Vector3.zero;
}
if (getTeleportPosition && (Object)(object)entrance.entrancePoint != (Object)null)
{
return entrance.entrancePoint.position;
}
return ((Object)(object)((Component)entrance).transform != (Object)null) ? ((Component)entrance).transform.position : Vector3.zero;
}
private static bool IsCompanyLevel()
{
SelectableLevel val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.currentLevel : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
return val.levelID == 3 || string.Equals(val.sceneName, "CompanyBuilding", StringComparison.OrdinalIgnoreCase) || (val.PlanetName != null && val.PlanetName.IndexOf("company", StringComparison.OrdinalIgnoreCase) >= 0);
}
private static void Warn(string message)
{
if (_warningCount < 5)
{
_warningCount++;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({_warningCount}/{5})");
}
}
}
}
[HarmonyPatch(typeof(HUDManager), "AddChatMessage")]
internal static class HUDManagerAddChatMessagePatch
{
private const int MaxWarnings = 5;
private static int _warningCount;
private static bool Prefix(HUDManager __instance)
{
if (IsHudChatReady(__instance, out var missingDependency))
{
return true;
}
Warn("Skipped HUDManager.AddChatMessage because chat HUD was not ready: " + missingDependency + ".");
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warn("Suppressed HUDManager.AddChatMessage NullReferenceException while chat HUD was not ready.");
return null;
}
return __exception;
}
internal static bool IsHudChatReady(HUDManager hudManager, out string missingDependency)
{
if ((Object)(object)hudManager == (Object)null)
{
missingDependency = "HUDManager";
return false;
}
if (hudManager.Chat == null)
{
missingDependency = "HUDManager.Chat";
return false;
}
if ((Object)(object)hudManager.chatText == (Object)null)
{
missingDependency = "HUDManager.chatText";
return false;
}
if (hudManager.ChatMessageHistory == null)
{
missingDependency = "HUDManager.ChatMessageHistory";
return false;
}
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
missingDependency = "GameNetworkManager.Instance";
return false;
}
if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
{
missingDependency = "GameNetworkManager.Instance.localPlayerController";
return false;
}
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
missingDependency = "StartOfRound.Instance";
return false;
}
if (StartOfRound.Instance.allPlayerScripts == null || StartOfRound.Instance.allPlayerScripts.Length < 4)
{
missingDependency = "StartOfRound.Instance.allPlayerScripts";
return false;
}
int num = Math.Min(4, StartOfRound.Instance.allPlayerScripts.Length);
for (int i = 0; i < num; i++)
{
if ((Object)(object)StartOfRound.Instance.allPlayerScripts[i] == (Object)null)
{
missingDependency = $"StartOfRound.Instance.allPlayerScripts[{i}]";
return false;
}
}
missingDependency = string.Empty;
return true;
}
internal static void Warn(string message)
{
if (_warningCount < 5)
{
_warningCount++;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({_warningCount}/{5})");
}
}
}
}
[HarmonyPatch(typeof(HUDManager), "AddTextMessageClientRpc")]
internal static class HUDManagerAddTextMessageClientRpcPatch
{
private static bool Prefix(HUDManager __instance)
{
if (HUDManagerAddChatMessagePatch.IsHudChatReady(__instance, out var missingDependency))
{
return true;
}
HUDManagerAddChatMessagePatch.Warn("Skipped HUDManager.AddTextMessageClientRpc because chat HUD was not ready: " + missingDependency + ".");
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
HUDManagerAddChatMessagePatch.Warn("Suppressed HUDManager.AddTextMessageClientRpc NullReferenceException while chat HUD was not ready.");
return null;
}
return __exception;
}
}
[HarmonyPatch(typeof(HUDManager), "SyncAllPlayerLevelsServerRpc", new Type[] { })]
internal static class HUDManagerSyncAllPlayerLevelsServerRpcPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(HUDManager __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)((NetworkBehaviour)__instance).NetworkManager == (Object)null || !((NetworkBehaviour)__instance).NetworkManager.IsListening)
{
return false;
}
if ((((NetworkBehaviour)__instance).NetworkManager.IsClient || ((NetworkBehaviour)__instance).NetworkManager.IsHost) && ((NetworkBehaviour)__instance).OwnerClientId != ((NetworkBehaviour)__instance).NetworkManager.LocalClientId)
{
Warnings.Warn("not-owner", "Skipped HUDManager.SyncAllPlayerLevelsServerRpc because the local client does not own HUDManager.");
return false;
}
return true;
}
}
[HarmonyPatch(typeof(InteractTrigger), "UpdateUsedByPlayerClientRpc")]
internal static class InteractTriggerUpdateUsedByPlayerClientRpcPatch
{
private const int MaxWarnings = 5;
private static int _warningCount;
private static bool Prefix(InteractTrigger __instance, int playerNum)
{
if (IsInteractRpcReady(__instance, playerNum, out var missingDependency))
{
return true;
}
Warn($"Skipped InteractTrigger.UpdateUsedByPlayerClientRpc for player {playerNum} because dependencies were not ready: {missingDependency}.");
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warn("Suppressed InteractTrigger.UpdateUsedByPlayerClientRpc NullReferenceException while trigger dependencies were not ready.");
return null;
}
return __exception;
}
private static bool IsInteractRpcReady(InteractTrigger trigger, int playerNum, out string missingDependency)
{
if ((Object)(object)trigger == (Object)null)
{
missingDependency = "InteractTrigger";
return false;
}
if (trigger.onInteractEarlyOtherClients == null)
{
missingDependency = GetTriggerName(trigger) + ".onInteractEarlyOtherClients";
return false;
}
if (!TryGetPlayer(playerNum, out var player, out missingDependency))
{
return false;
}
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
missingDependency = "GameNetworkManager.Instance";
return false;
}
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
if ((Object)(object)localPlayerController == (Object)null || (Object)(object)((Component)localPlayerController).transform == (Object)null)
{
missingDependency = "GameNetworkManager.Instance.localPlayerController";
return false;
}
if (trigger.specialCharacterAnimation && trigger.setVehicleAnimation && (Object)(object)player.gameplayCamera == (Object)null)
{
missingDependency = $"player {playerNum} gameplayCamera";
return false;
}
missingDependency = string.Empty;
return true;
}
private static bool TryGetPlayer(int playerNum, out PlayerControllerB player, out string missingDependency)
{
player = null;
if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null || playerNum < 0 || playerNum >= StartOfRound.Instance.allPlayerScripts.Length)
{
missingDependency = "StartOfRound.Instance.allPlayerScripts";
return false;
}
player = StartOfRound.Instance.allPlayerScripts[playerNum];
if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).transform == (Object)null)
{
missingDependency = $"StartOfRound.Instance.allPlayerScripts[{playerNum}]";
return false;
}
missingDependency = string.Empty;
return true;
}
private static string GetTriggerName(InteractTrigger trigger)
{
return ((Object)(object)trigger != (Object)null && (Object)(object)((Component)trigger).gameObject != (Object)null) ? ((Object)((Component)trigger).gameObject).name : "unknown trigger";
}
private static void Warn(string message)
{
if (_warningCount < 5)
{
_warningCount++;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({_warningCount}/{5})");
}
}
}
}
[HarmonyPatch(typeof(RadMechAI), "SetExplosion")]
internal static class RadMechAISetExplosionPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(Exception __exception)
{
return SuppressKnownException(__exception, "RadMechAI.SetExplosion", Warnings);
}
internal static Exception SuppressKnownException(Exception exception, string key, WarningLimiter warnings)
{
if (exception is NullReferenceException)
{
warnings.Warn(key, "Suppressed " + key + " NullReferenceException.");
return null;
}
return exception;
}
}
[HarmonyPatch(typeof(RadMechAI), "SetExplosionClientRpc")]
internal static class RadMechAISetExplosionClientRpcPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(Exception __exception)
{
return RadMechAISetExplosionPatch.SuppressKnownException(__exception, "RadMechAI.SetExplosionClientRpc", Warnings);
}
}
[HarmonyPatch(typeof(JetpackItem), "DeactivateJetpack")]
internal static class JetpackItemDeactivateJetpackPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(Exception __exception)
{
return RadMechAISetExplosionPatch.SuppressKnownException(__exception, "JetpackItem.DeactivateJetpack", Warnings);
}
}
[HarmonyPatch(typeof(JetpackItem), "ItemActivate")]
internal static class JetpackItemItemActivatePatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(Exception __exception)
{
return RadMechAISetExplosionPatch.SuppressKnownException(__exception, "JetpackItem.ItemActivate", Warnings);
}
}
[HarmonyPatch(typeof(GrabbableObject), "ActivateItemRpc")]
internal static class GrabbableObjectActivateItemRpcPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(GrabbableObject __instance, Exception __exception)
{
if (!(__instance is JetpackItem))
{
return __exception;
}
return RadMechAISetExplosionPatch.SuppressKnownException(__exception, "GrabbableObject.ActivateItemRpc", Warnings);
}
}
[HarmonyPatch(typeof(LobbySlot), "SetModdedIcon")]
internal static class LobbySlotSetModdedIconPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(LobbySlot __instance, ModdedState moddedState)
{
//IL_0026: 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: Invalid comparison between Unknown and I4
if ((Object)(object)__instance == (Object)null)
{
Warnings.Warn("null-slot", "Skipped LobbySlot.SetModdedIcon because the lobby slot was null.");
return false;
}
if ((int)moddedState == 0 && (Object)(object)__instance.modStateUnknownIcon == (Object)null)
{
Warnings.Warn("missing-unknown-icon", "Skipped LobbySlot.SetModdedIcon because modStateUnknownIcon was missing.");
return false;
}
if ((int)moddedState == 2 && (Object)(object)__instance.modStateTrueIcon == (Object)null)
{
Warnings.Warn("missing-modded-icon", "Skipped LobbySlot.SetModdedIcon because modStateTrueIcon was missing.");
return false;
}
return true;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("finalizer-null-reference", "Suppressed LobbySlot.SetModdedIcon NullReferenceException.");
return null;
}
return __exception;
}
}
[HarmonyPatch(typeof(DisplayPlayerMicVolume), "InitMic")]
internal static class DisplayPlayerMicVolumeInitMicPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(DisplayPlayerMicVolume __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)IngamePlayerSettings.Instance == (Object)null || IngamePlayerSettings.Instance.unsavedSettings == null)
{
return false;
}
IngamePlayerSettings.Instance.RefreshAndDisplayCurrentMicrophone(false);
string micDevice = IngamePlayerSettings.Instance.unsavedSettings.micDevice;
if (!IsValidMicrophoneDevice(micDevice))
{
return false;
}
Traverse val = Traverse.Create((object)__instance);
string value = val.Field("_device").GetValue<string>();
if (IsValidMicrophoneDevice(value) && Microphone.IsRecording(value))
{
Microphone.End(value);
}
try
{
int num = default(int);
int num2 = default(int);
Microphone.GetDeviceCaps(micDevice, ref num, ref num2);
int num3 = ((num2 <= 0) ? 44100 : Mathf.Clamp(44100, Mathf.Max(num, 1), num2));
val.Field("_device").SetValue((object)micDevice);
val.Field("_clipRecord").SetValue((object)Microphone.Start(micDevice, true, 1, num3));
}
catch (Exception ex) when (ex is ArgumentException || ex is InvalidOperationException)
{
Warn("Skipping microphone preview for unavailable device '" + micDevice + "': " + ex.Message);
val.Field("_clipRecord").SetValue((object)null);
}
return false;
}
internal static void Warn(string message)
{
Warnings.Warn("DisplayPlayerMicVolume", message);
}
internal static bool IsValidMicrophoneDevice(string device)
{
if (string.IsNullOrWhiteSpace(device) || device == "none" || device == "LCNoMic" || Microphone.devices == null)
{
return false;
}
return Array.IndexOf(Microphone.devices, device) >= 0;
}
}
[HarmonyPatch(typeof(DisplayPlayerMicVolume), "StopMicrophone")]
internal static class DisplayPlayerMicVolumeStopMicrophonePatch
{
private static bool Prefix(DisplayPlayerMicVolume __instance)
{
if ((Object)(object)__instance == (Object)null)
{
return false;
}
try
{
string value = Traverse.Create((object)__instance).Field("_device").GetValue<string>();
if (DisplayPlayerMicVolumeInitMicPatch.IsValidMicrophoneDevice(value) && Microphone.IsRecording(value))
{
Microphone.End(value);
}
}
catch (Exception ex)
{
DisplayPlayerMicVolumeInitMicPatch.Warn("Skipping microphone stop because it failed safely: " + ex.GetType().Name);
}
return false;
}
}
[HarmonyPatch(typeof(DisplayPlayerMicVolume), "LevelMax")]
internal static class DisplayPlayerMicVolumeLevelMaxPatch
{
private static bool Prefix(DisplayPlayerMicVolume __instance, ref float __result)
{
__result = 0f;
if ((Object)(object)__instance == (Object)null || (Object)(object)IngamePlayerSettings.Instance == (Object)null || IngamePlayerSettings.Instance.unsavedSettings == null)
{
return false;
}
string micDevice = IngamePlayerSettings.Instance.unsavedSettings.micDevice;
if (!DisplayPlayerMicVolumeInitMicPatch.IsValidMicrophoneDevice(micDevice) || !Microphone.IsRecording(micDevice))
{
return false;
}
try
{
AudioClip value = Traverse.Create((object)__instance).Field("_clipRecord").GetValue<AudioClip>();
return (Object)(object)value != (Object)null;
}
catch (Exception ex)
{
DisplayPlayerMicVolumeInitMicPatch.Warn("Skipping microphone level preview because it failed safely: " + ex.GetType().Name);
return false;
}
}
}
[HarmonyPatch(typeof(NavMeshSurface), "CollectSources")]
internal static class NavMeshSurfaceCollectSourcesPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static readonly WarningLimiter GuardFailureWarnings = new WarningLimiter();
private static void Postfix(NavMeshSurface __instance, ref List<NavMeshBuildSource> __result)
{
try
{
FilterUnreadableMeshSources(__instance, __result);
}
catch (Exception ex)
{
GuardFailureWarnings.Warn("guard-failure", "NavMeshSurface source filter failed safely and left sources unchanged: " + ex.GetType().Name + ".");
}
}
private static void FilterUnreadableMeshSources(NavMeshSurface surface, List<NavMeshBuildSource> sources)
{
//IL_0048: 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_004f: Unknown result type (might be due to invalid IL or missing references)
if (sources == null || sources.Count == 0)
{
return;
}
int num = 0;
string surfaceName = GetSurfaceName(surface);
bool flag = ShouldLog(surfaceName);
HashSet<string> hashSet = (flag ? new HashSet<string>() : null);
for (int num2 = sources.Count - 1; num2 >= 0; num2--)
{
NavMeshBuildSource source = sources[num2];
if (TryGetUnreadableMesh(source, out var mesh))
{
sources.RemoveAt(num2);
num++;
hashSet?.Add(GetMeshName(mesh));
}
}
if (num > 0 && flag)
{
Warn(surfaceName, hashSet, num);
}
}
private static bool TryGetUnreadableMesh(NavMeshBuildSource source, out Mesh mesh)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
mesh = null;
if ((int)((NavMeshBuildSource)(ref source)).shape == 0)
{
Object sourceObject = ((NavMeshBuildSource)(ref source)).sourceObject;
Mesh val = (Mesh)(object)((sourceObject is Mesh) ? sourceObject : null);
if (val != null && !((Object)(object)val == (Object)null))
{
mesh = val;
return !val.isReadable;
}
}
return false;
}
private static bool ShouldLog(string surfaceName)
{
string key = "unreadable-navmesh-sources|" + surfaceName;
return Warnings.CanWarn(key);
}
private static void Warn(string surfaceName, HashSet<string> meshNames, int removedCount)
{
string key = "unreadable-navmesh-sources|" + surfaceName;
Warnings.Warn(key, delegate
{
string arg = ((meshNames != null && meshNames.Count > 0) ? string.Join(", ", meshNames) : "unknown");
return $"Filtered {removedCount} unreadable mesh source(s) from NavMeshSurface '{surfaceName}' before runtime NavMesh build: {arg}.";
});
}
private static string GetSurfaceName(NavMeshSurface surface)
{
return ((Object)(object)surface != (Object)null && (Object)(object)((Component)surface).gameObject != (Object)null) ? ((Object)((Component)surface).gameObject).name : "unknown";
}
private static string GetMeshName(Mesh mesh)
{
return ((Object)(object)mesh != (Object)null && !string.IsNullOrEmpty(((Object)mesh).name)) ? ((Object)mesh).name : "unnamed mesh";
}
}
[HarmonyPatch(typeof(EnemyAI), "DoAIInterval")]
internal static class EnemyAINavMeshGuardPatch
{
private const float RecoveryAttemptCooldown = 0.5f;
private const float RecoveryCacheCleanupInterval = 30f;
private static readonly float[] SampleRadii = new float[5] { 2f, 4f, 8f, 16f, 32f };
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static readonly Dictionary<int, float> NextRecoveryAttemptTimes = new Dictionary<int, float>();
private static float _nextRecoveryCacheCleanupTime;
private static bool Prefix(EnemyAI __instance)
{
try
{
return GuardEnemyAIInterval(__instance);
}
catch (Exception ex)
{
string enemyName = GetEnemyName(__instance);
Warn(enemyName, "NavMesh guard failed safely for " + enemyName + ": " + ex.GetType().Name + ".");
return true;
}
}
private static bool GuardEnemyAIInterval(EnemyAI enemy)
{
if ((Object)(object)enemy == (Object)null || enemy.inSpecialAnimation || (Object)(object)enemy.agent == (Object)null || !enemy.moveTowardsDestination || !((Behaviour)enemy.agent).enabled || enemy.agent.isOnNavMesh)
{
return true;
}
string enemyName = GetEnemyName(enemy);
if (!CanAttemptRecovery(enemy))
{
return false;
}
if (!((NetworkBehaviour)enemy).IsOwner)
{
Warn(enemyName, "Suppressed non-owner " + enemyName + " SetDestination while its NavMeshAgent is off the NavMesh.");
return false;
}
if (enemy.isEnemyDead)
{
enemy.moveTowardsDestination = false;
TrySyncPositionToClients(enemy);
Warn(enemyName, "Suppressed " + enemyName + " SetDestination while it is dead and its NavMeshAgent is off the NavMesh.");
return false;
}
if (TryWarpToNearbyNavMesh(enemy))
{
Warn(enemyName, "Recovered " + enemyName + " NavMeshAgent by warping it back onto the NavMesh.");
return true;
}
enemy.moveTowardsDestination = false;
TrySyncPositionToClients(enemy);
Warn(enemyName, "Suppressed " + enemyName + " SetDestination while its NavMeshAgent is off the NavMesh and no nearby NavMesh point was found.");
return false;
}
private static bool TryWarpToNearbyNavMesh(EnemyAI enemy)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
int areaMask = enemy.agent.areaMask;
Vector3 position = ((Component)enemy).transform.position;
if (TryWarpToNearbyNavMesh(enemy, position, areaMask))
{
return true;
}
return areaMask != -1 && TryWarpToNearbyNavMesh(enemy, position, -1);
}
private static bool TryWarpToNearbyNavMesh(EnemyAI enemy, Vector3 position, int areaMask)
{
//IL_0006: 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_0030: Unknown result type (might be due to invalid IL or missing references)
NavMeshHit val = default(NavMeshHit);
for (int i = 0; i < SampleRadii.Length; i++)
{
if (NavMesh.SamplePosition(position, ref val, SampleRadii[i], areaMask) && IsUsableRecoveryPoint(enemy, ((NavMeshHit)(ref val)).position, areaMask) && enemy.agent.Warp(((NavMeshHit)(ref val)).position))
{
if (enemy.agent.isOnNavMesh)
{
enemy.agent.ResetPath();
}
return true;
}
}
return false;
}
private static bool IsUsableRecoveryPoint(EnemyAI enemy, Vector3 position, int areaMask)
{
//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)
//IL_0038: 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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Invalid comparison between Unknown and I4
if (enemy.destination == Vector3.zero)
{
return true;
}
NavMeshPath val = enemy.path1;
if (val == null)
{
val = (enemy.path1 = new NavMeshPath());
}
return NavMesh.CalculatePath(position, enemy.destination, areaMask, val) && (int)val.status != 2;
}
private static bool CanAttemptRecovery(EnemyAI enemy)
{
int instanceID = ((Object)enemy).GetInstanceID();
float realtimeSinceStartup = Time.realtimeSinceStartup;
CleanupRecoveryCacheIfNeeded(realtimeSinceStartup);
if (NextRecoveryAttemptTimes.TryGetValue(instanceID, out var value) && realtimeSinceStartup < value)
{
return false;
}
NextRecoveryAttemptTimes[instanceID] = realtimeSinceStartup + 0.5f;
return true;
}
private static void Warn(string enemyName, string message)
{
Warnings.Warn(enemyName, message);
}
private static void CleanupRecoveryCacheIfNeeded(float now)
{
if (now < _nextRecoveryCacheCleanupTime || NextRecoveryAttemptTimes.Count < 128)
{
return;
}
_nextRecoveryCacheCleanupTime = now + 30f;
List<int> list = null;
foreach (KeyValuePair<int, float> nextRecoveryAttemptTime in NextRecoveryAttemptTimes)
{
if (!(nextRecoveryAttemptTime.Value >= now))
{
if (list == null)
{
list = new List<int>();
}
list.Add(nextRecoveryAttemptTime.Key);
}
}
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
NextRecoveryAttemptTimes.Remove(list[i]);
}
}
}
private static string GetEnemyName(EnemyAI enemy)
{
if ((Object)(object)enemy == (Object)null)
{
return "Unknown Enemy";
}
if ((Object)(object)enemy.enemyType != (Object)null && !string.IsNullOrEmpty(enemy.enemyType.enemyName))
{
return enemy.enemyType.enemyName;
}
return ((Object)enemy).name;
}
private static void TrySyncPositionToClients(EnemyAI enemy)
{
try
{
enemy.SyncPositionToClients();
}
catch (Exception ex)
{
Warn(GetEnemyName(enemy), "Skipped EnemyAI position sync after NavMesh guard because it failed safely: " + ex.GetType().Name + ".");
}
}
}
[HarmonyPatch]
internal static class NetworkObjectDestroyGuardPatch
{
[CompilerGenerated]
private sealed class <TargetMethods>d__4 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__4(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(Object), "Destroy", new Type[1] { typeof(Object) }, (Type[])null);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(Object), "Destroy", new Type[2]
{
typeof(Object),
typeof(float)
}, (Type[])null);
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__4(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
private const float WarningInterval = 5f;
private static readonly Dictionary<ulong, float> LastWarningTimes = new Dictionary<ulong, float>();
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static readonly WarningLimiter GuardFailureWarnings = new WarningLimiter();
[IteratorStateMachine(typeof(<TargetMethods>d__4))]
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__4(-2);
}
private static bool Prefix(Object obj)
{
try
{
return ShouldAllowDestroy(obj);
}
catch (Exception ex)
{
GuardFailureWarnings.Warn("guard-failure", "NetworkObject destroy guard failed safely and allowed original Destroy: " + ex.GetType().Name + ".");
return true;
}
}
private static bool ShouldAllowDestroy(Object obj)
{
if (obj == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer)
{
return true;
}
bool flag = obj is GameObject;
GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
if ((Object)(object)val == (Object)null)
{
Component val2 = (Component)(object)((obj is Component) ? obj : null);
if (val2 != null)
{
val = val2.gameObject;
}
}
if ((Object)(object)val == (Object)null)
{
return true;
}
RagdollGrabbableObject val3 = val.GetComponent<RagdollGrabbableObject>() ?? val.GetComponentInParent<RagdollGrabbableObject>();
if ((Object)(object)val3 == (Object)null && flag)
{
val3 = val.GetComponentInChildren<RagdollGrabbableObject>();
}
if ((Object)(object)val3 == (Object)null)
{
return true;
}
NetworkObject component = ((Component)val3).GetComponent<NetworkObject>();
if ((Object)(object)component == (Object)null || !component.IsSpawned)
{
return true;
}
WarnBlockedDestroy(component);
return false;
}
private static void WarnBlockedDestroy(NetworkObject networkObject)
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (!LastWarningTimes.TryGetValue(networkObject.NetworkObjectId, out var value) || !(realtimeSinceStartup - value < 5f))
{
LastWarningTimes[networkObject.NetworkObjectId] = realtimeSinceStartup;
Warnings.Warn($"blocked-destroy|{networkObject.NetworkObjectId}", "Blocked client-side Destroy on spawned " + ((Object)networkObject).name + "; waiting for server despawn.");
}
}
}
[HarmonyPatch]
internal static class NetworkObjectParentChangedPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
[HarmonyPrepare]
private static bool Prepare()
{
return TargetMethod() != null;
}
[HarmonyTargetMethod]
private static MethodBase TargetMethod()
{
return AccessTools.Method(typeof(NetworkObject), "OnTransformParentChanged", (Type[])null, (Type[])null);
}
private static bool Prefix(NetworkObject __instance)
{
if ((Object)(object)__instance == (Object)null || __instance.IsSpawned)
{
return true;
}
Warnings.Warn(GetWarningKey(__instance), () => "Skipped NetworkObject.OnTransformParentChanged for unspawned object '" + GetObjectName(__instance) + "' to avoid invalid reparent handling.");
return false;
}
private static Exception Finalizer(NetworkObject __instance, Exception __exception)
{
if (IsKnownSpawnStateException(__exception))
{
Warnings.Warn(GetWarningKey(__instance), () => "Suppressed NetworkObject reparent SpawnStateException for '" + GetObjectName(__instance) + "'.");
return null;
}
return __exception;
}
private static bool IsKnownSpawnStateException(Exception exception)
{
return exception != null && exception.GetType().Name == "SpawnStateException" && exception.Message != null && exception.Message.Contains("NetworkObject can only be reparented after being spawned");
}
private static string GetWarningKey(NetworkObject networkObject)
{
return ((Object)(object)networkObject != (Object)null) ? $"network-parent|{((Object)networkObject).GetInstanceID()}" : "network-parent|unknown";
}
private static string GetObjectName(NetworkObject networkObject)
{
return ((Object)(object)networkObject != (Object)null) ? ((Object)networkObject).name : "unknown";
}
}
[HarmonyPatch]
internal static class EnemyHealthBarsLateUpdatePatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
[HarmonyPrepare]
private static bool Prepare()
{
return TargetMethod() != null;
}
[HarmonyTargetMethod]
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("EnemyHealthBars.Scripts.HealthBar");
return OptionalPatchTargetResolver.FindMethod(type, "LateUpdate", false, typeof(void));
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("EnemyHealthBars.HealthBar.LateUpdate", "Suppressed EnemyHealthBars.HealthBar.LateUpdate NullReferenceException.");
return null;
}
return __exception;
}
}
[HarmonyPatch]
internal static class ShipLootPlusUiHelperPatch
{
[CompilerGenerated]
private sealed class <TargetMethods>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
private Type <uiHelperType>5__1;
private HashSet<MethodBase> <yieldedMethods>5__2;
private MethodBase <calculateLootValue>5__3;
private MethodBase <refreshElementValues>5__4;
private Type[] <>s__5;
private int <>s__6;
private Type <nestedType>5__7;
private MethodInfo[] <>s__8;
private int <>s__9;
private MethodInfo <method>5__10;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<uiHelperType>5__1 = null;
<yieldedMethods>5__2 = null;
<calculateLootValue>5__3 = null;
<refreshElementValues>5__4 = null;
<>s__5 = null;
<nestedType>5__7 = null;
<>s__8 = null;
<method>5__10 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<uiHelperType>5__1 = AccessTools.TypeByName("ShipLootPlus.Utils.UiHelper");
if (<uiHelperType>5__1 == null)
{
return false;
}
<yieldedMethods>5__2 = new HashSet<MethodBase>();
<calculateLootValue>5__3 = OptionalPatchTargetResolver.FindMethod(<uiHelperType>5__1, "CalculateLootValue", true, null, typeof(List<GrabbableObject>), typeof(string));
if (<calculateLootValue>5__3 != null && <yieldedMethods>5__2.Add(<calculateLootValue>5__3))
{
<>2__current = <calculateLootValue>5__3;
<>1__state = 1;
return true;
}
goto IL_00e4;
case 1:
<>1__state = -1;
goto IL_00e4;
case 2:
<>1__state = -1;
goto IL_014e;
case 3:
{
<>1__state = -1;
<method>5__10 = null;
goto IL_020a;
}
IL_0218:
if (<>s__9 < <>s__8.Length)
{
<method>5__10 = <>s__8[<>s__9];
if (!ShouldPatchGeneratedMethod(<nestedType>5__7, <method>5__10) || !<yieldedMethods>5__2.Add(<method>5__10))
{
goto IL_020a;
}
<>2__current = <method>5__10;
<>1__state = 3;
return true;
}
<>s__8 = null;
<nestedType>5__7 = null;
<>s__6++;
goto IL_0248;
IL_014e:
<>s__5 = <uiHelperType>5__1.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
<>s__6 = 0;
goto IL_0248;
IL_0248:
if (<>s__6 < <>s__5.Length)
{
<nestedType>5__7 = <>s__5[<>s__6];
<>s__8 = <nestedType>5__7.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
<>s__9 = 0;
goto IL_0218;
}
<>s__5 = null;
return false;
IL_020a:
<>s__9++;
goto IL_0218;
IL_00e4:
<refreshElementValues>5__4 = OptionalPatchTargetResolver.FindMethod(<uiHelperType>5__1, "RefreshElementValues", true, typeof(void));
if (<refreshElementValues>5__4 != null && <yieldedMethods>5__2.Add(<refreshElementValues>5__4))
{
<>2__current = <refreshElementValues>5__4;
<>1__state = 2;
return true;
}
goto IL_014e;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__2(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
private static readonly WarningLimiter Warnings = new WarningLimiter();
[HarmonyPrepare]
private static bool Prepare()
{
return AccessTools.TypeByName("ShipLootPlus.Utils.UiHelper") != null;
}
[IteratorStateMachine(typeof(<TargetMethods>d__2))]
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__2(-2);
}
private static Exception Finalizer(MethodBase __originalMethod, Exception __exception)
{
if (__exception is NullReferenceException)
{
string text = ((__originalMethod != null) ? __originalMethod.Name : "unknown");
Warnings.Warn("ShipLootPlus.UiHelper." + text, "Compatibility guard handled ShipLootPlus.UiHelper." + text + " NullReferenceException while refreshing loot UI.");
return null;
}
return __exception;
}
private static bool ShouldPatchGeneratedMethod(Type nestedType, MethodInfo method)
{
if (nestedType == null || method == null)
{
return false;
}
return method.ReturnType == typeof(bool) && (method.Name.Contains("<CalculateLootValue>") || (method.Name == "MoveNext" && nestedType.Name.Contains("<UpdateDatapoints>")));
}
}
[HarmonyPatch]
internal static class NightVisionInsideLightingPostfixPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
[HarmonyPrepare]
private static bool Prepare()
{
return TargetMethod() != null;
}
[HarmonyTargetMethod]
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("NightVision.Patches.NightVisionOutdoors");
return OptionalPatchTargetResolver.FindMethod(type, "InsideLightingPostfix", true, typeof(void), typeof(TimeOfDay));
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("NightVision.InsideLightingPostfix", "Compatibility guard handled NightVision outdoors lighting NullReferenceException while inside lighting changed.");
return null;
}
return __exception;
}
}
[HarmonyPatch]
internal static class ChatCommandApiStartHostPostfixPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
[HarmonyPrepare]
private static bool Prepare()
{
return TargetMethod() != null;
}
[HarmonyTargetMethod]
private static MethodBase TargetMethod()
{
Type type = AccessTools.TypeByName("ChatCommandAPI.Patches.GameNetworkManager_StartHost");
return OptionalPatchTargetResolver.FindMethod(type, "Postfix", true, typeof(void));
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("ChatCommandAPI.GameNetworkManager_StartHost.Postfix", "Compatibility guard handled ChatCommandAPI StartHost Postfix NullReferenceException while hosting a lobby.");
return null;
}
return __exception;
}
}
internal static class OptionalPatchTargetResolver
{
internal static MethodBase FindMethod(Type type, string methodName, bool isStatic, Type returnType, params Type[] parameterTypes)
{
if (type == null)
{
return null;
}
MethodInfo methodInfo = AccessTools.Method(type, methodName, parameterTypes, (Type[])null);
if (methodInfo == null || methodInfo.IsStatic != isStatic || (returnType != null && methodInfo.ReturnType != returnType))
{
return null;
}
return methodInfo;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "NearOtherPlayers")]
internal static class PlayerControllerBNearOtherPlayersPatch
{
private static bool Prefix(PlayerControllerB __instance, float checkRadius, ref bool __result)
{
try
{
return CheckNearOtherPlayersSafely(__instance, checkRadius, ref __result);
}
catch (Exception exception)
{
__result = false;
return NullRefGuard.Suppress(exception, "PlayerControllerB.NearOtherPlayers") != null;
}
}
private static bool CheckNearOtherPlayersSafely(PlayerControllerB __instance, float checkRadius, ref bool __result)
{
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).transform == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
{
__result = false;
return false;
}
float num = checkRadius * checkRadius;
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val in allPlayerScripts)
{
if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)__instance) && val.isPlayerControlled && !((Object)(object)((Component)val).transform == (Object)null))
{
Vector3 val2 = ((Component)__instance).transform.position - ((Component)val).transform.position;
if (((Vector3)(ref val2)).sqrMagnitude < num)
{
__result = true;
return false;
}
}
}
__result = false;
return false;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "PlayJumpAudio")]
internal static class PlayerControllerBPlayJumpAudioPatch
{
private const int MaxWarnings = 5;
private static int _warningCount;
private static bool Prefix(PlayerControllerB __instance)
{
try
{
PlayJumpAudioSafely(__instance);
}
catch (Exception ex)
{
Warn("Skipped PlayerControllerB.PlayJumpAudio because the guard failed safely: " + ex.GetType().Name + ".");
}
return false;
}
private static void PlayJumpAudioSafely(PlayerControllerB player)
{
if ((Object)(object)player == (Object)null || (Object)(object)player.movementAudio == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
Warn("Skipped PlayerControllerB.PlayJumpAudio because audio dependencies were not ready.");
return;
}
string missingDependency;
AudioClip val = TryGetSuitJumpAudio(player, out missingDependency) ?? TryGetDefaultJumpAudio(ref missingDependency);
if ((Object)(object)val == (Object)null)
{
Warn("Skipped PlayerControllerB.PlayJumpAudio because no jump audio clip was available: " + missingDependency + ".");
return;
}
if (!string.IsNullOrEmpty(missingDependency))
{
Warn("Used default jump audio because suit jump audio was not available: " + missingDependency + ".");
}
player.movementAudio.PlayOneShot(val);
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is ArgumentOutOfRangeException || __exception is NullReferenceException)
{
Warn("Suppressed PlayerControllerB.PlayJumpAudio " + __exception.GetType().Name + ".");
return null;
}
return __exception;
}
private static AudioClip TryGetSuitJumpAudio(PlayerControllerB player, out string missingDependency)
{
missingDependency = string.Empty;
if ((Object)(object)StartOfRound.Instance.unlockablesList == (Object)null || StartOfRound.Instance.unlockablesList.unlockables == null)
{
missingDependency = "StartOfRound.Instance.unlockablesList";
return null;
}
if (player.currentSuitID < 0 || player.currentSuitID >= StartOfRound.Instance.unlockablesList.unlockables.Count)
{
missingDependency = $"currentSuitID {player.currentSuitID} outside unlockables count {StartOfRound.Instance.unlockablesList.unlockables.Count}";
return null;
}
UnlockableItem val = StartOfRound.Instance.unlockablesList.unlockables[player.currentSuitID];
if (val == null)
{
missingDependency = $"unlockables[{player.currentSuitID}]";
return null;
}
AudioClip jumpAudio = val.jumpAudio;
if ((Object)(object)jumpAudio == (Object)null)
{
missingDependency = $"unlockables[{player.currentSuitID}].jumpAudio";
}
return jumpAudio;
}
private static AudioClip TryGetDefaultJumpAudio(ref string missingDependency)
{
if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.playerJumpSFX == (Object)null)
{
missingDependency = (string.IsNullOrEmpty(missingDependency) ? "StartOfRound.Instance.playerJumpSFX" : (missingDependency + "; StartOfRound.Instance.playerJumpSFX"));
return null;
}
return StartOfRound.Instance.playerJumpSFX;
}
internal static void Warn(string message)
{
if (_warningCount < 5)
{
_warningCount++;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({_warningCount}/{5})");
}
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "PlayerJumpedClientRpc")]
internal static class PlayerControllerBPlayerJumpedClientRpcPatch
{
private static Exception Finalizer(Exception __exception)
{
if (__exception is ArgumentOutOfRangeException || __exception is NullReferenceException)
{
PlayerControllerBPlayJumpAudioPatch.Warn("Suppressed PlayerControllerB.PlayerJumpedClientRpc " + __exception.GetType().Name + " from jump audio playback.");
return null;
}
return __exception;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "ThrowObjectClientRpc")]
internal static class PlayerControllerBThrowObjectClientRpcPatch
{
private const int MaxWarnings = 5;
private static readonly Dictionary<string, int> WarningCounts = new Dictionary<string, int>();
private static readonly FieldInfo RpcExecStageField = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_exec_stage");
private static readonly FieldInfo ThrowingObjectField = AccessTools.Field(typeof(PlayerControllerB), "throwingObject");
private static readonly object RpcExecStageSend = ((RpcExecStageField != null) ? Enum.Parse(RpcExecStageField.FieldType, "Send") : null);
private static bool Prefix(PlayerControllerB __instance, bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, NetworkObjectReference grabbedObject, int floorYRot)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (!IsExecutingClientRpc(__instance))
{
return true;
}
try
{
HandleThrowObjectClientRpcSafely(__instance, droppedInElevator, droppedInShipRoom, targetFloorPosition, grabbedObject, floorYRot);
}
catch (Exception ex)
{
Warn("guard-failed", "Suppressed ThrowObjectClientRpc because the guard failed safely: " + ex.GetType().Name + ".");
SetRpcExecStageSend(__instance);
if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).IsOwner)
{
SetThrowingObject(__instance, value: false);
}
}
return false;
}
private static void HandleThrowObjectClientRpcSafely(PlayerControllerB player, bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, NetworkObjectReference grabbedObject, int floorYRot)
{
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)player == (Object)null || (Object)(object)((NetworkBehaviour)player).NetworkManager == (Object)null || !((NetworkBehaviour)player).NetworkManager.IsListening || (!((NetworkBehaviour)player).NetworkManager.IsClient && !((NetworkBehaviour)player).NetworkManager.IsHost))
{
return;
}
SetRpcExecStageSend(player);
NetworkObject val = default(NetworkObject);
if (((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null) && (Object)(object)val != (Object)null)
{
GrabbableObject component = ((Component)val).GetComponent<GrabbableObject>();
if ((Object)(object)component == (Object)null)
{
Warn($"missing-grabbable|{player.playerClientId}", $"Skipped ThrowObjectClientRpc for player #{player.playerClientId} because the NetworkObject had no GrabbableObject.");
FinishThrowingIfOwner(player);
return;
}
if (!((NetworkBehaviour)player).IsOwner)
{
player.SetObjectAsNoLongerHeld(droppedInElevator, droppedInShipRoom, targetFloorPosition, component, floorYRot);
}
if ((Object)(object)component.itemProperties == (Object)null || !component.itemProperties.syncDiscardFunction)
{
component.playerHeldBy = null;
}
if ((Object)(object)component == (Object)(object)player.currentlyHeldObjectServer)
{
player.currentlyHeldObjectServer = null;
}
else
{
Warn($"held-mismatch|{player.playerClientId}", $"Suppressed ThrowObjectClientRpc held-object mismatch for player #{player.playerClientId}; currentlyHeldObjectServer was {GetHeldObjectName(player.currentlyHeldObjectServer)}.");
}
}
else
{
Warn($"missing-network-object|{player.playerClientId}", $"Suppressed ThrowObjectClientRpc because the server object reference was missing for player #{player.playerClientId}.");
}
FinishThrowingIfOwner(player);
}
private static bool IsExecutingClientRpc(PlayerControllerB player)
{
if ((Object)(object)player == (Object)null || RpcExecStageField == null)
{
return false;
}
object value = RpcExecStageField.GetValue(player);
return value != null && value.ToString() == "Execute";
}
private static string GetHeldObjectName(GrabbableObject heldObject)
{
if ((Object)(object)heldObject == (Object)null)
{
return "null";
}
return ((Object)(object)((Component)heldObject).gameObject != (Object)null) ? ((Object)((Component)heldObject).gameObject).name : "missing GameObject";
}
private static void SetRpcExecStageSend(PlayerControllerB player)
{
if ((Object)(object)player != (Object)null && RpcExecStageField != null && RpcExecStageSend != null)
{
RpcExecStageField.SetValue(player, RpcExecStageSend);
}
}
private static void FinishThrowingIfOwner(PlayerControllerB player)
{
if ((Object)(object)player != (Object)null && ((NetworkBehaviour)player).IsOwner)
{
SetThrowingObject(player, value: false);
}
}
private static void SetThrowingObject(PlayerControllerB player, bool value)
{
if ((Object)(object)player != (Object)null && ThrowingObjectField != null)
{
ThrowingObjectField.SetValue(player, value);
}
}
private static void Warn(string key, string message)
{
WarningCounts.TryGetValue(key, out var value);
if (value < 5)
{
value++;
WarningCounts[key] = value;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({value}/{5})");
}
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
internal static class PlayerControllerBGrabObjectClientRpcPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(PlayerControllerB __instance, Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("GrabObjectClientRpc|" + GetPlayerId(__instance), "Suppressed PlayerControllerB.GrabObjectClientRpc NullReferenceException for player #" + GetPlayerId(__instance) + ".");
return null;
}
return __exception;
}
private static string GetPlayerId(PlayerControllerB player)
{
return ((Object)(object)player != (Object)null) ? player.playerClientId.ToString() : "unknown";
}
}
[HarmonyPatch(typeof(QuicksandTrigger), "OnExit")]
internal static class QuicksandTriggerOnExitPatch
{
private const int MaxWarnings = 5;
private static readonly Dictionary<string, int> WarningCounts = new Dictionary<string, int>();
private static bool Prefix(QuicksandTrigger __instance, Collider other)
{
try
{
HandleExitSafely(__instance, other);
}
catch (Exception ex)
{
Warn("exception", "Suppressed QuicksandTrigger.OnExit failure safely: " + ex.GetType().Name + ".");
}
return false;
}
private static void HandleExitSafely(QuicksandTrigger quicksandTrigger, Collider other)
{
if ((Object)(object)quicksandTrigger == (Object)null || (Object)(object)other == (Object)null)
{
Warn("missing-trigger-or-collider", "Skipped QuicksandTrigger.OnExit because the trigger or collider was missing.");
return;
}
PlayerControllerB val = TryGetPlayer(other);
if ((Object)(object)val == (Object)null)
{
if (((Component)other).CompareTag("Player"))
{
Warn("missing-player", "Skipped QuicksandTrigger.OnExit for '" + ((Object)other).name + "' because no PlayerControllerB was found.");
}
return;
}
if ((Object)(object)GameNetworkManager.Instance == (Object)null)
{
Warn("missing-network-manager", "Skipped QuicksandTrigger.OnExit because GameNetworkManager.Instance was missing.");
return;
}
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
if (!quicksandTrigger.sinkingLocalPlayer)
{
if (quicksandTrigger.isWater && (Object)(object)val != (Object)(object)localPlayerController)
{
val.isUnderwater = false;
}
}
else if ((Object)(object)val == (Object)(object)localPlayerController)
{
quicksandTrigger.StopSinkingLocalPlayer(val);
}
}
private static PlayerControllerB TryGetPlayer(Collider other)
{
if ((Object)(object)other == (Object)null || (Object)(object)((Component)other).gameObject == (Object)null)
{
return null;
}
return ((Component)other).gameObject.GetComponent<PlayerControllerB>() ?? ((Component)other).GetComponentInParent<PlayerControllerB>();
}
private static void Warn(string key, string message)
{
WarningCounts.TryGetValue(key, out var value);
if (value < 5)
{
value++;
WarningCounts[key] = value;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)$"{message} ({value}/{5})");
}
}
}
}
[HarmonyPatch(typeof(RedLocustBees), "IsHiveMissing")]
internal static class RedLocustBeesIsHiveMissingPatch
{
private static bool Prefix(RedLocustBees __instance, ref bool __result)
{
//IL_0058: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: 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_0125: 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)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)((EnemyAI)__instance).eye == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
__result = false;
return false;
}
if ((Object)(object)__instance.hive == (Object)null)
{
__result = true;
return false;
}
float num = Vector3.Distance(((EnemyAI)__instance).eye.position, __instance.lastKnownHivePosition);
if (!Traverse.Create((object)__instance).Field("syncedLastKnownHivePosition").GetValue<bool>())
{
__result = false;
return false;
}
bool flag = num < 8f && !Physics.Linecast(((EnemyAI)__instance).eye.position, __instance.lastKnownHivePosition, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
if (num < 4f || flag)
{
if ((Vector3.Distance(((Component)__instance.hive).transform.position, __instance.lastKnownHivePosition) > 6f && !IsHivePlacedAndInLOS(__instance)) || __instance.hive.isHeld)
{
__result = true;
return false;
}
__instance.lastKnownHivePosition = ((Component)__instance.hive).transform.position + Vector3.up * 0.5f;
}
__result = false;
return false;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "RedLocustBees.IsHiveMissing");
}
private static bool IsHivePlacedAndInLOS(RedLocustBees bees)
{
//IL_0047: 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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)bees.hive == (Object)null || (Object)(object)((EnemyAI)bees).eye == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || bees.hive.isHeld)
{
return false;
}
return Vector3.Distance(((EnemyAI)bees).eye.position, ((Component)bees.hive).transform.position) <= 9f && !Physics.Linecast(((EnemyAI)bees).eye.position, ((Component)bees.hive).transform.position, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
}
}
[HarmonyPatch(typeof(RedLocustBees), "IsHivePlacedAndInLOS")]
internal static class RedLocustBeesIsHivePlacedAndInLOSPatch
{
private static bool Prefix(RedLocustBees __instance, ref bool __result)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.hive == (Object)null || (Object)(object)((EnemyAI)__instance).eye == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || __instance.hive.isHeld)
{
__result = false;
return false;
}
__result = Vector3.Distance(((EnemyAI)__instance).eye.position, ((Component)__instance.hive).transform.position) <= 9f && !Physics.Linecast(((EnemyAI)__instance).eye.position, ((Component)__instance.hive).transform.position, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
return false;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "RedLocustBees.IsHivePlacedAndInLOS");
}
}
[HarmonyPatch(typeof(RedLocustBees), "DoAIInterval")]
internal static class RedLocustBeesDoAIIntervalPatch
{
private static bool Prefix(RedLocustBees __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
return false;
}
if (!Traverse.Create((object)__instance).Field("hasSpawnedHive").GetValue<bool>() || (Object)(object)__instance.hive != (Object)null)
{
return true;
}
((EnemyAI)__instance).targetPlayer = null;
((EnemyAI)__instance).movingTowardsTargetPlayer = false;
if (((EnemyAI)__instance).currentBehaviourStateIndex != 2)
{
((EnemyAI)__instance).SwitchToBehaviourState(2);
}
return false;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "RedLocustBees.DoAIInterval");
}
}
[HarmonyPatch(typeof(RedLocustBees), "Update")]
internal static class RedLocustBeesUpdatePatch
{
private static bool Prefix(RedLocustBees __instance)
{
if ((Object)(object)__instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
{
return false;
}
if ((Object)(object)((EnemyAI)__instance).agent == (Object)null || (Object)(object)__instance.beeParticles == (Object)null || (Object)(object)__instance.beeParticlesTarget == (Object)null)
{
return false;
}
return true;
}
private static Exception Finalizer(Exception __exception)
{
return NullRefGuard.Suppress(__exception, "RedLocustBees.Update");
}
}
[HarmonyPatch(typeof(SandSpiderAI), "PlayerLeaveWebClientRpc")]
internal static class SandSpiderAIPlayerLeaveWebClientRpcPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static Exception Finalizer(int trapID, int playerNum, Exception __exception)
{
if (__exception is ArgumentOutOfRangeException)
{
Warnings.Warn($"PlayerLeaveWebClientRpc|trap:{trapID}|player:{playerNum}", $"Suppressed SandSpiderAI.PlayerLeaveWebClientRpc ArgumentOutOfRangeException for trap {trapID}, player {playerNum}.");
return null;
}
return __exception;
}
}
[HarmonyPatch(typeof(GrabbableObjectPhysicsTrigger), "OnTriggerEnter")]
internal static class GrabbableObjectPhysicsTriggerOnTriggerEnterPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(GrabbableObjectPhysicsTrigger __instance, Collider other)
{
if ((Object)(object)__instance?.itemScript != (Object)null && (Object)(object)((other != null) ? ((Component)other).gameObject : null) != (Object)null)
{
return true;
}
Warnings.Warn("missing-trigger-dependency", "Skipped GrabbableObjectPhysicsTrigger.OnTriggerEnter because itemScript or collider was missing.");
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("nre", "Suppressed GrabbableObjectPhysicsTrigger.OnTriggerEnter NullReferenceException.");
return null;
}
return __exception;
}
}
[HarmonyPatch(typeof(SoccerBallProp), "ActivatePhysicsTrigger")]
internal static class SoccerBallPropActivatePhysicsTriggerPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(SoccerBallProp __instance, Collider other)
{
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00b7: 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_00c1: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance == (Object)null || (Object)(object)((other != null) ? ((Component)other).gameObject : null) == (Object)null)
{
Warnings.Warn("missing-trigger", "Skipped SoccerBallProp.ActivatePhysicsTrigger because the ball or collider was missing.");
return false;
}
GameObject gameObject = ((Component)other).gameObject;
if (!IsPlayerOrEnemy(gameObject))
{
return false;
}
if ((Object)(object)StartOfRound.Instance == (Object)null)
{
Warnings.Warn("missing-startofround", "Skipped SoccerBallProp.ActivatePhysicsTrigger because StartOfRound was not ready.");
return false;
}
Vector3 val = gameObject.transform.position + Vector3.up;
Vector3 val2 = ((Component)__instance).transform.position + Vector3.up * 0.5f;
if (!Physics.Linecast(val, val2, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
{
__instance.BeginKickBall(val, gameObject.CompareTag("Enemy"));
}
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("nre", "Suppressed SoccerBallProp.ActivatePhysicsTrigger NullReferenceException.");
return null;
}
return __exception;
}
private static bool IsPlayerOrEnemy(GameObject gameObject)
{
return (Object)(object)gameObject != (Object)null && (gameObject.CompareTag("Player") || gameObject.CompareTag("Enemy"));
}
}
[HarmonyPatch(typeof(SoccerBallProp), "BeginKickBall")]
internal static class SoccerBallPropBeginKickBallPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(SoccerBallProp __instance, bool hitByEnemy)
{
if ((Object)(object)__instance != (Object)null && ((hitByEnemy && !((NetworkBehaviour)__instance).IsServer) || ((GrabbableObject)__instance).isHeld || (Object)(object)((GrabbableObject)__instance).parentObject != (Object)null))
{
return false;
}
if (HasRequiredKickDependencies(__instance))
{
return true;
}
Warnings.Warn("missing-kick-dependency", "Skipped SoccerBallProp.BeginKickBall because required ball, round, player, or ship references were missing.");
return false;
}
private static Exception Finalizer(Exception __exception)
{
if (__exception is NullReferenceException)
{
Warnings.Warn("nre", "Suppressed SoccerBallProp.BeginKickBall NullReferenceException.");
return null;
}
return __exception;
}
private static bool HasRequiredKickDependencies(SoccerBallProp ball)
{
if ((Object)(object)ball == (Object)null || (Object)(object)((Component)ball).transform == (Object)null || (Object)(object)((GrabbableObject)ball).itemProperties == (Object)null)
{
return false;
}
StartOfRound instance = StartOfRound.Instance;
RoundManager instance2 = RoundManager.Instance;
GameNetworkManager instance3 = GameNetworkManager.Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3?.localPlayerController == (Object)null)
{
return false;
}
return (Object)(object)instance.elevatorTransform != (Object)null && (Object)(object)instance.propsContainer != (Object)null && (Object)(object)instance.shipBounds != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null && (Object)(object)instance2.spawnedScrapContainer != (Object)null;
}
}
[HarmonyPatch(typeof(SoundManager), "PlayAmbienceClipLocal")]
internal static class SoundManagerPlayAmbienceClipLocalPatch
{
private static readonly WarningLimiter Warnings = new WarningLimiter();
private static bool Prefix(SoundManager __instance, int soundType, int clipIndex, float soundVolume, bool playInsanitySounds)
{
try
{
return IsAmbienceClipValid(__instance, soundType, clipIndex, playInsanitySounds);
}
catch (Exception ex)
{
Warnings.Warn("guard-failed", "SoundManager.PlayAmbienceClipLocal guard failed safely and allowed original playback: " + ex.GetType().Name + ".");
return true;
}
}
private static Exception Finalizer(int soundType, int clipIndex, bool playInsanitySounds, Exception __exception)
{
if (__exception is IndexOutOfRangeException)
{
Warnings.Warn($"index-exception|{soundType}|{playInsanitySounds}", $"Suppressed SoundManager.PlayAmbienceClipLocal IndexOutOfRangeException for soundType {soundType}, clipIndex {clipIndex}, playInsanitySounds={playInsanitySounds}.");
return null;
}
return __exception;
}
private static bool IsAmbienceClipValid(SoundManager soundManager, int soundType, int clipIndex, bool playInsanitySounds)
{
if ((Object)(object)soundManager == (Object)null || (Object)(object)soundManager.currentLevelAmbience == (Object)null)
{
Warnings.Warn("missing-ambience", "Skipped SoundManager.PlayAmbienceClipLocal because currentLevelAmbience was missing.");
return false;
}
if (clipIndex < 0)
{
Warnings.Warn($"negative-index|{soundType}|{playInsanitySounds}", $"Skipped SoundManager.PlayAmbienceClipLocal because clipIndex {clipIndex} was negative for soundType {soundType}.");
return false;
}
LevelAmbienceLibrary currentLevelAmbience = soundManager.currentLevelAmbience;
if (playInsanitySounds)
{
return IsInsanityClipValid(currentLevelAmbience, soundType, clipIndex);
}
return IsNormalClipValid(currentLevelAmbience, soundType, clipIndex);
}
private static bool IsNormalClipValid(LevelAmbienceLibrary ambience, int soundType, int clipIndex)
{
if (1 == 0)
{
}
AudioClip[] array = soundType switch
{
0 => ambience.insideAmbience,
1 => ambience.outsideAmbience,
2 => ambience.shipAmbience,
_ => null,
};
if (1 == 0)
{
}
AudioClip[] array2 = array;
if (array2 != null && clipIndex < array2.Length && (Object)(object)array2[clipIndex] != (Object)null)
{
return true;
}
WarnInvalidIndex(soundType, clipIndex, playInsanitySounds: false, (array2 != null) ? array2.Length : 0);
return false;
}
private static bool IsInsanityClipValid(LevelAmbienceLibrary ambience, int soundType, int clipIndex)
{
if (1 == 0)
{
}
RandomAudioClip[] array = soundType switch
{
0 => ambience.insideAmbienceInsanity,
1 => ambience.outsideAmbienceInsanity,
2 => ambience.shipAmbienceInsanity,
_ => null,
};
if (1 == 0)
{
}
RandomAudioClip[] array2 = array;
if (array2 != null && clipIndex < array2.Length && array2[clipIndex] != null && (Object)(object)array2[clipIndex].audioClip != (Object)null)
{
return true;
}
WarnInvalidIndex(soundType, clipIndex, playInsanitySounds: