Decompiled source of PracticeSandbox v0.1.79

BepInEx\plugins\PracticeSandbox\PracticeSandbox.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.goshujinsama.PracticeSandbox")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.github.goshujinsama.PracticeSandbox")]
[assembly: AssemblyTitle("PracticeSandbox")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace PracticeSandbox
{
	[BepInPlugin("com.github.goshujinsama.PracticeSandbox", "Practice Sandbox", "0.1.79.8")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.github.goshujinsama.PracticeSandbox";

		public const string ModName = "Practice Sandbox";

		public const string ModVersion = "0.1.79.8";

		internal static ManualLogSource Log;

		private readonly Harmony harmony = new Harmony("com.github.goshujinsama.PracticeSandbox");

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Practice Sandbox 0.1.79.8 loaded (stable: persistent multi-Fox mold / BushWolf rescue recovery / terminal restore).");
			harmony.PatchAll();
			PracticeController.PatchEnemyNoiseDetection(harmony);
			PracticeController.PatchBrackenKillAnimationGuard(harmony);
		}

		private void Update()
		{
			PracticeController.RuntimeFrameTick("Plugin.Update");
		}
	}
	internal static class PracticeDiagnosticFile
	{
		private static readonly object Gate = new object();

		private static StreamWriter writer;

		internal static string LogPath { get; private set; } = "";

		internal static void Initialize()
		{
			LogPath = "";
		}

		[Conditional("PRACTICE_SANDBOX_DIAGNOSTICS")]
		internal static void Write(string tag, string message)
		{
		}
	}
	internal enum PracticeSpawnMode
	{
		Normal,
		CircuitBees,
		GiantSapsucker,
		KidnapperFox
	}
	internal enum EnemyOnlyCageMode
	{
		Off,
		Floor,
		Full
	}
	internal enum PracticeJesterSpawnMode
	{
		Default,
		PreCrank,
		Popped
	}
	internal sealed class EnemyDefinition
	{
		public string DisplayName { get; }

		public string PrimaryAlias { get; }

		public string[] Aliases { get; }

		public string[] SearchWords { get; }

		public string[] ExcludeWords { get; }

		public EnemyType? EnemyType { get; set; }

		public bool PreferOutside { get; }

		public PracticeSpawnMode SpawnMode { get; }

		public EnemyDefinition(string displayName, string primaryAlias, bool preferOutside, PracticeSpawnMode spawnMode, string[] searchWords, string[]? extraAliases = null, string[]? excludeWords = null)
		{
			DisplayName = displayName;
			PrimaryAlias = PracticeController.Normalize(primaryAlias);
			PreferOutside = preferOutside;
			SpawnMode = spawnMode;
			List<string> list = new List<string> { PrimaryAlias };
			if (extraAliases != null)
			{
				list.AddRange(extraAliases.Select(PracticeController.Normalize));
			}
			Aliases = list.Where((string alias) => !string.IsNullOrWhiteSpace(alias)).Distinct().ToArray();
			List<string> list2 = new List<string> { displayName };
			list2.AddRange(searchWords ?? Array.Empty<string>());
			SearchWords = list2.Where((string word) => !string.IsNullOrWhiteSpace(word)).Select(PracticeController.Normalize).Distinct()
				.ToArray();
			ExcludeWords = (excludeWords ?? Array.Empty<string>()).Where((string word) => !string.IsNullOrWhiteSpace(word)).Select(PracticeController.Normalize).Distinct()
				.ToArray();
		}
	}
	internal sealed class PracticeItemDefinition
	{
		public string DisplayName { get; }

		public string NormalizedName { get; }

		public string Alias { get; }

		public Item Item { get; }

		public bool IsBuyable { get; }

		public bool IsScrap { get; }

		public PracticeItemDefinition(Item item, string alias, bool isBuyable, bool isScrap)
		{
			Item = item;
			DisplayName = item.itemName ?? ((Object)item).name ?? "Unknown item";
			NormalizedName = PracticeController.Normalize(DisplayName);
			Alias = PracticeController.Normalize(alias);
			IsBuyable = isBuyable;
			IsScrap = isScrap;
		}
	}
	internal readonly struct ParsedCommand
	{
		public string Name { get; }

		public int Count { get; }

		public ParsedCommand(string name, int count)
		{
			Name = name;
			Count = count;
		}
	}
	internal sealed class PracticeSpecialSpawnGroup
	{
		public int GroupId;

		public int EnemyInstanceId;

		public string Origin = "";

		public Vector3 Center;

		public EnemyAI? Enemy;

		public readonly List<GameObject> StructuralObjects = new List<GameObject>();

		public readonly List<Vector3> StructuralPositions = new List<Vector3>();

		public readonly List<GrabbableObject> LootObjects = new List<GrabbableObject>();

		public readonly HashSet<int> RegisteredObjectIds = new HashSet<int>();

		public float ResolveUntilTime;

		public bool LayoutApplied;

		public float NextDiagnosticTime;
	}
	internal sealed class PracticeBoundsBoxVisual
	{
		public GameObject? Root;

		public Mesh? Mesh;

		public Renderer? Renderer;

		public Material? Material;

		public Vector3[] Vertices = (Vector3[])(object)new Vector3[96];

		public float Thickness;

		public string RenderMethod = "CombinedMeshEdges/CreateVisibleMaterial";
	}
	internal sealed class PracticeSpecialLootRecord
	{
		public GrabbableObject? Item;

		public int GroupId;

		public string Origin = "";

		public PracticeBoundsBoxVisual? Marker;

		public string MarkerBoundsSource = "uninitialized";

		public float NextMarkerDiagnosticTime;
	}
	internal sealed class PracticeHitboxVisual
	{
		public Collider? Collider;

		public PracticeBoundsBoxVisual? Box;

		public bool Attack;
	}
	internal static class PracticeController
	{
		internal static bool PracticeQueued = false;

		internal static bool PracticeActive = false;

		internal static bool ManualEnemySpawnInProgress = false;

		internal static bool ArenaCreated = false;

		internal static readonly List<EnemyAI> SpawnedEnemies = new List<EnemyAI>();

		private static readonly List<GameObject> ArenaObjects = new List<GameObject>();

		private static readonly List<GameObject> PracticeSpawnedUtilityObjects = new List<GameObject>();

		private static readonly List<PracticeSpecialSpawnGroup> PracticeSpecialSpawnGroups = new List<PracticeSpecialSpawnGroup>();

		private static readonly Dictionary<int, PracticeSpecialLootRecord> PracticeSpecialLootByInstanceId = new Dictionary<int, PracticeSpecialLootRecord>();

		private static readonly List<GameObject> PracticeSpecialStructuralObjects = new List<GameObject>();

		private static readonly List<PracticeHitboxVisual> PracticeHitboxVisuals = new List<PracticeHitboxVisual>();

		private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestTargets = new Dictionary<int, Vector3>();

		private static readonly HashSet<int> PracticeGiantKiwiNestOverrideLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestOriginalPositions = new Dictionary<int, Vector3>();

		private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestMoveDeltas = new Dictionary<int, Vector3>();

		private static readonly HashSet<int> PracticeGiantKiwiNestRelocatedIds = new HashSet<int>();

		private static readonly HashSet<int> PracticeGiantKiwiEggRelocatedIds = new HashSet<int>();

		private static readonly Dictionary<int, Vector3> PracticeGiantKiwiHomePositions = new Dictionary<int, Vector3>();

		private static readonly Dictionary<int, float> PracticeGiantKiwiHomeRestoreDueTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> PracticeGiantKiwiHomeRestoreLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> PracticeGiantKiwiKillStackLoggedIds = new HashSet<int>();

		internal static bool PracticeManualMoldGenerationInProgress = false;

		private static float nextInvAbyssRescueAllowedTime = 0f;

		private static int nextSpecialSpawnGroupId = 1;

		private static bool PracticeStatsOverlayEnabled = true;

		private static bool PracticeHitboxOverlayEnabled = false;

		private static float nextSpecialSpawnResolveTime = 0f;

		private static bool hitboxRefreshDirty = false;

		private static string hitboxDirtyReason = "initial";

		private static float nextHitboxTransformUpdateTime = 0f;

		private static float nextHitboxPlayerRosterCheckTime = 0f;

		private static int lastHitboxRemotePlayerCount = -1;

		private static float nextSpecialLootVisualUpdateTime = 0f;

		private static float nextFastBoundaryTickTime = 0f;

		private static float nextPlayerFacilityFlagTime = 0f;

		private static float nextAwarenessFastTickTime = 0f;

		private static GUIStyle? practiceHpGuiStyle;

		private static GUIStyle? practiceStGuiStyle;

		private static GUIStyle? practiceShadowGuiStyle;

		private static float nextStatsOverlayDiagTime = 0f;

		private static float nextHitboxRuntimeDiagTime = 0f;

		private static bool statsOverlayFirstDrawLogged = false;

		private static int hitboxCreateFailureCount = 0;

		private static string hitboxLastCreateError = "";

		private const bool TargetedChatDebugEnabled = false;

		private const bool TargetedHitboxDebugEnabled = false;

		private const bool TargetedOldBirdThreatDebugEnabled = false;

		private static bool practiceChatHandledThisSubmit = false;

		private static string practicePendingChatResult = "";

		private static string practicePendingChatRaw = "";

		private static int practiceChatSequence = 0;

		private static readonly Dictionary<string, float> OldBirdThreatEventNextLogTimes = new Dictionary<string, float>();

		private static readonly Dictionary<string, float> GiantKiwiThreatEventNextLogTimes = new Dictionary<string, float>();

		private static readonly Dictionary<int, float> OldBirdThreatSnapshotNextTimes = new Dictionary<int, float>();

		private static readonly Dictionary<Type, MemberInfo[]> OldBirdThreatMembersByType = new Dictionary<Type, MemberInfo[]>();

		private static readonly Dictionary<int, string> OldBirdThreatCapabilityByEnemyId = new Dictionary<int, string>();

		private static readonly Dictionary<int, float> OldBirdNonPlayerThreatSeenSince = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> OldBirdEntityAlertAssistCooldownUntil = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> OldBirdEntityAttackSeenSince = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> OldBirdEntityAttackAssistCooldownUntil = new Dictionary<int, float>();

		private static readonly HashSet<int> BrackenMemberInventoryLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, int> BrackenLastBehaviourStateById = new Dictionary<int, int>();

		private static readonly Dictionary<int, float> BrackenLastStateLogTimeById = new Dictionary<int, float>();

		private static bool baboonGroupRefreshPending = false;

		private static float baboonGroupRefreshAt = 0f;

		private static string baboonGroupLastSignature = "";

		private static GameObject? PracticeBaboonCampObject;

		private static bool practiceAmbientEffectsDisabled = false;

		private static readonly HashSet<int> PracticeManuallySpawnedItemIds = new HashSet<int>();

		private static readonly List<GameObject> PendingFoxGrassObjects = new List<GameObject>();

		private static Vector3 PendingFoxGrassCenter = Vector3.zero;

		private static bool ambientSourceInventoryLogged = false;

		private static bool initialLooseItemCleanupDone = false;

		private static float initialLooseItemCleanupAt = 0f;

		private static int lastRuntimeFrameTick = -1;

		private static float nextRuntimeDriverDiagTime = 0f;

		private static string lastRuntimeDriverSource = "none";

		private static GameObject? practiceStatsCanvasObject;

		private static Component? practiceStatsTextComponent;

		private static RectTransform? practiceStatsTextRect;

		private static float nextStatsHudDiagTime = 0f;

		private static float nextStatsHudUpdateTime = 0f;

		private static bool practiceStatsFixedPositionCaptured = false;

		private static Vector2 practiceStatsFixedAnchoredPosition = new Vector2(210f, -70f);

		private static bool statsHudCreatedLogged = false;

		private static string practiceStatsLastRenderedText = "";

		private static readonly List<Renderer> DisabledMapRenderers = new List<Renderer>();

		private static readonly List<Collider> DisabledMapColliders = new List<Collider>();

		private static readonly List<Terrain> DisabledTerrains = new List<Terrain>();

		private static readonly List<NavMeshData> PracticeNavMeshDataList = new List<NavMeshData>();

		private static readonly List<NavMeshDataInstance> PracticeNavMeshInstances = new List<NavMeshDataInstance>();

		private static readonly Dictionary<int, float> EnemyBarrierPushCooldown = new Dictionary<int, float>();

		private static readonly HashSet<int> JesterPracticePoppedIds = new HashSet<int>();

		private static readonly HashSet<int> JesterPracticeNoResetArmedIds = new HashSet<int>();

		private static readonly HashSet<int> JesterPracticePreCrankIds = new HashSet<int>();

		private static readonly HashSet<int> JesterInitializationSeenIds = new HashSet<int>();

		private static readonly HashSet<int> JesterCrankStartedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> JesterSequenceNextDiagTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> JesterMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> ForcedAdultManeaterIds = new HashSet<int>();

		private static readonly Dictionary<int, float> MouthDogDirectLungeNextTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> DogDeepDiagNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> DogMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> ManeaterRecoveryUntilTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> ManeaterDeepDiagNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> ManeaterMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> ManeaterDeferredResetIds = new HashSet<int>();

		private static readonly HashSet<int> ManeaterResetInProgressIds = new HashSet<int>();

		private static readonly Dictionary<int, string> ManeaterDeferredResetReasons = new Dictionary<int, string>();

		private static readonly Dictionary<int, float> OldBirdDiagNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> OldBirdMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> OldBirdWakeAttemptedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> ForestGiantDiagNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> ForestGiantMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> EnemyPostSpawnIdentityLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> DogKeywordMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> OldBirdKeywordMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> ForestGiantKeywordMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, int> ForestGiantZeroAnimatorMotionFrames = new Dictionary<int, int>();

		private static readonly Dictionary<int, float> ForestGiantAnimatorFixNextLogTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> ForestGiantLifecycleHookNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> ForestGiantStaleEatRecoveryAttemptedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> ForestGiantVisionAssistNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> DogSpawnAnimatorRecoveredIds = new HashSet<int>();

		private static readonly Dictionary<int, float> OldBirdSpawnRealtimeById = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> OldBirdEarlyKillLogNextTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> MaskedDiagNextTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> MaskedLifecycleHookNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> MaskedMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> MaskedKeywordMethodInventoryLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> MaskedResetDueTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, string> MaskedResetReasons = new Dictionary<int, string>();

		private static readonly HashSet<int> MaskedPendingPostFinishResetIds = new HashSet<int>();

		private static readonly HashSet<int> MaskedCancelStackLoggedIds = new HashSet<int>();

		private static readonly HashSet<int> OldBirdDespawnStackLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> ForestGiantPassiveDiagNextTimes = new Dictionary<int, float>();

		private static readonly List<GameObject> PracticeOldBirdNestObjects = new List<GameObject>();

		private static readonly Dictionary<int, float> ForestGiantVisionProbeNextTimes = new Dictionary<int, float>();

		private static readonly HashSet<int> ForestGiantSpawnFinishedLoggedIds = new HashSet<int>();

		private static readonly Dictionary<int, float> MaskedCollisionSuppressUntil = new Dictionary<int, float>();

		private static readonly Dictionary<int, string> MaskedNextFrameRearmReasons = new Dictionary<int, string>();

		private static bool PracticeDeletionInProgress = false;

		private static readonly Dictionary<string, PracticeItemDefinition> CachedItemsByNormalizedName = new Dictionary<string, PracticeItemDefinition>();

		private static readonly Dictionary<string, int> StoreItemOrderByNormalizedName = new Dictionary<string, int>();

		private static readonly HashSet<string> LevelSpawnableScrapNormalizedNames = new HashSet<string>();

		private static readonly List<PracticeItemDefinition> CachedPracticeItems = new List<PracticeItemDefinition>();

		internal static Vector3 PracticeAreaCenter;

		internal static float PracticeAreaHalfSize = 60f;

		internal static Vector3 EnemyAreaCenter;

		internal static float EnemyAreaHalfSize = 25f;

		private static Vector3 EnemyAreaForward = Vector3.forward;

		private static Vector3 EnemyAreaRight = Vector3.right;

		private static bool UseInvertedShipRightAsFront = true;

		private static float nextRuntimeTickTime = 0f;

		private static float nextSlowTickTime = 0f;

		private static float nextEnemyRescanTime = 0f;

		private static float nextArenaAttemptTime = 0f;

		private static float arenaCreationAllowedTime = 0f;

		private static float nextTerminalInteractionRepairTime = 0f;

		private static readonly HashSet<int> ShipTerminalProtectedObjectIds = new HashSet<int>();

		private static float lateWorldCleanupDueTime = 0f;

		private static bool lateWorldCleanupPending = false;

		private static readonly Dictionary<int, float> OldBirdDeepDiagNextTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> BushWolfPostRescueResetDueTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, int> BushWolfPostRescueResetAttempts = new Dictionary<int, int>();

		private static GameObject PracticeFoxGrassTemplate = null;

		private static readonly Dictionary<int, float> BushWolfOriginalBaseOffsets = new Dictionary<int, float>();

		private static readonly Dictionary<int, int> BushWolfGrowlCounts = new Dictionary<int, int>();

		private static readonly Dictionary<int, float> BushWolfGrowlLastTimes = new Dictionary<int, float>();

		private static float nextNoonTimeForceTime = 0f;

		private static float localPlayerPostHealCleanupUntilTime = 0f;

		private const bool DiagnosticLoggingEnabled = false;

		private static float nextPluginUpdateDiagnosticTime = 0f;

		private static float nextArenaDiagnosticLogTime = 0f;

		private static float nextNavMeshDiagnosticLogTime = 0f;

		private static float nextEnemySummaryDiagnosticTime = 0f;

		private static readonly Dictionary<int, float> EnemyDiagnosticNextLogTimes = new Dictionary<int, float>();

		private static bool floorPostProcessingArenaAttempted = false;

		private static bool LocalPlayerInvincible = false;

		private static float nextInvincibleDetailedDiagTime = 0f;

		private static bool lastInvincibleObservedDeadState = false;

		private static bool invincibleFieldInventoryLogged = false;

		private static bool AutoRescueEnabled = true;

		private static bool PracticeCriticalInjuryEnabled = true;

		private static bool CriticalVisualHealthGateEnabled = true;

		private const int CriticalVisualClearHealthThreshold = 20;

		private static float nextCriticalVisualHealthGateTime = 0f;

		private static int lastCriticalGateObservedHealth = -1;

		private static bool lastCriticalGateObservedCritical = false;

		private static bool criticalVisualClearAppliedForHealthyState = false;

		private static bool ManeaterHardRefreshEnabled = false;

		private static bool ManeaterForceAdultVisualEnabled = false;

		private static bool ManeaterAdultRespawnFromAdultEnabled = true;

		private static bool JesterPracticeAggroEnabled = true;

		private static bool JesterPracticeNoResetEnabled = true;

		private static bool MouthDogPracticeChargeEnabled = true;

		private const float JesterPracticeCrankDelaySeconds = 2.5f;

		private const float JesterPracticePopDelaySeconds = 4f;

		private const float MouthDogPracticeChargeSpeed = 18f;

		private const float MouthDogDirectLungeDistance = 24f;

		private const float ManeaterPracticeMinimumChaseSpeed = 18f;

		private const float ManeaterPracticeAttackSpeed = 26f;

		private const float EnemyBoundaryInnerMargin = 4f;

		private static bool EnemyRedBoundaryGuardEnabled = true;

		private static bool EnemyLeashEnabled = false;

		private static bool TulipContinuousCollisionDiagnostics = false;

		private static bool TulipBoundaryGuardEnabled = true;

		private static bool HidePlayersOutsideEnemyAreaFromEnemies = true;

		private static bool pendingLocalPlayerRescueScheduled = false;

		private static float pendingLocalPlayerRescueTime = 0f;

		private static string pendingLocalPlayerRescueReason = "";

		private static float nextAwarenessSuppressionTime = 0f;

		private static EnemyOnlyCageMode CurrentEnemyOnlyCageMode = EnemyOnlyCageMode.Off;

		private static readonly List<GameObject> EnemyOnlyCageObjects = new List<GameObject>();

		private static readonly List<Collider> EnemyOnlyCageColliders = new List<Collider>();

		private static readonly List<Collider> EnemyBoundaryWallColliders = new List<Collider>();

		private const float EnemyBoundaryEmergencyReturnOvershoot = 3f;

		private static readonly Dictionary<int, float> CageDiagnosticNextLogTimes = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> TulipBoundaryGuardNextTimes = new Dictionary<int, float>();

		private static bool roundManagerRefreshAttempted = false;

		private static bool itemCacheDirty = true;

		private const float PlatformWidth = 120f;

		private const float PlatformLength = 120f;

		private const float PlatformThickness = 0.6f;

		private const float EnemySpawnHeightAbovePlatform = 2f;

		private const float EnemyAreaWidth = 52f;

		private const float EnemyAreaLength = 52f;

		private const float PlatformTopOffsetFromShip = -2.05f;

		private const float EnemyAreaNearEdgeFromShip = 20f;

		private const float PlayerRespawnDistanceFromShip = 14f;

		private const int PracticeNavMeshAreaMask = 1;

		private const float PracticeNavMeshHeightTolerance = 0.45f;

		private static readonly List<EnemyDefinition> EnemyDefinitions = new List<EnemyDefinition>
		{
			new EnemyDefinition("masked", "mas", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "masked" }),
			new EnemyDefinition("nutcracker", "nut", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "nutcracker" }),
			new EnemyDefinition("bracken", "bra", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "bracken", "flowerman" }, new string[1] { "da-" }),
			new EnemyDefinition("coilhead", "coi", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "coilhead", "springman", "spring" }),
			new EnemyDefinition("thumper", "thu", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "thumper", "crawler" }, new string[1] { "tam" }),
			new EnemyDefinition("spider", "spi", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "spider", "bunkerspider", "bunker spider" }),
			new EnemyDefinition("hoarder", "hoa", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "hoarder", "hoardingbug", "hoarding bug" }),
			new EnemyDefinition("hygrodere", "hyg", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "hygrodere", "slime", "blob" }),
			new EnemyDefinition("jester", "jes", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "jester" }),
			new EnemyDefinition("butler", "but", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "butler" }),
			new EnemyDefinition("dog", "dog", preferOutside: true, PracticeSpawnMode.Normal, new string[5] { "mouthdog", "mouth dog", "eyelessdog", "eyeless dog", "dog" }, new string[5] { "eye", "mouthdog", "mouth dog", "eyelessdog", "eyeless dog" }),
			new EnemyDefinition("baboonhawk", "bab", preferOutside: true, PracticeSpawnMode.Normal, new string[3] { "baboonhawk", "baboon hawk", "baboon" }),
			new EnemyDefinition("forestgiant", "for", preferOutside: true, PracticeSpawnMode.Normal, new string[3] { "forestgiant", "forest giant", "giant" }),
			new EnemyDefinition("oldbird", "old", preferOutside: true, PracticeSpawnMode.Normal, new string[4] { "oldbird", "old bird", "radmech", "rad mech" }, new string[5] { "bird", "oldbird", "old bird", "radmech", "rad mech" }),
			new EnemyDefinition("maneater", "man", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "maneater", "maneaterbaby", "maneater baby" }),
			new EnemyDefinition("barber", "bar", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "barber", "claysurgeon", "clay surgeon" }),
			new EnemyDefinition("tulipsnake", "tul", preferOutside: true, PracticeSpawnMode.Normal, new string[2] { "tulipsnake", "tulip snake" }),
			new EnemyDefinition("kidnapperfox", "kid", preferOutside: true, PracticeSpawnMode.KidnapperFox, new string[5] { "kidnapperfox", "kidnapper fox", "bushwolf", "bush wolf", "fox" }, new string[1] { "fox" }),
			new EnemyDefinition("circuitbees", "cir", preferOutside: true, PracticeSpawnMode.CircuitBees, new string[6] { "redlocustbees", "red locust bees", "redlocust", "circuitbees", "circuit bees", "circuit" }, new string[1] { "bee" }, new string[2] { "docile", "roaming" }),
			new EnemyDefinition("giantsapsucker", "gia", preferOutside: true, PracticeSpawnMode.GiantSapsucker, new string[7] { "giantsapsucker", "giant sapsucker", "sapsucker", "giantkiwi", "giant kiwi", "kiwi", "giantkiwiai" }, new string[1] { "sap" }),
			new EnemyDefinition("roaminglocust", "roa", preferOutside: true, PracticeSpawnMode.Normal, new string[5] { "docilelocustbees", "docile locust bees", "docilelocust", "roaminglocust", "roaming locust" }, new string[1] { "loc" }, new string[2] { "redlocust", "circuit" }),
			new EnemyDefinition("maskhornets", "hor", preferOutside: true, PracticeSpawnMode.Normal, new string[4] { "maskhornets", "mask hornets", "butlerbees", "butler bees" }),
			new EnemyDefinition("cadaverbloom", "blo", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "cadaverbloom", "cadaver bloom" }, new string[1] { "cad" }),
			new EnemyDefinition("lassoman", "las", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "lassoman", "lasso man" }),
			new EnemyDefinition("redpill", "red", preferOutside: false, PracticeSpawnMode.Normal, new string[5] { "redpill", "red pill", "redpillanomaly", "testenemy", "test enemy" }),
			new EnemyDefinition("ghostgirl", "gho", preferOutside: false, PracticeSpawnMode.Normal, new string[5] { "ghostgirl", "ghost girl", "dressgirl", "dress girl", "girl" }, new string[1] { "gir" })
		};

		private static readonly Dictionary<string, string> SpecialItemAliases = new Dictionary<string, string>
		{
			{ "shovel", "sho" },
			{ "shotgun", "shot" },
			{ "goldbar", "gbar" },
			{ "goldencup", "gcup" },
			{ "hairbrush", "hbru" },
			{ "hairdryer", "hdry" },
			{ "plasticcup", "pcup" },
			{ "plasticfish", "pfis" },
			{ "toycube", "toyc" },
			{ "toytrain", "toyt" },
			{ "toyrobot", "toyr" },
			{ "eggbeater", "eggb" },
			{ "clownhorn", "clow" },
			{ "clock", "cloc" },
			{ "magic7ball", "m7b" },
			{ "magnifyingglass", "magn" },
			{ "shotgunshells", "shs" },
			{ "beehive", "beh" },
			{ "hive", "beh" },
			{ "oldphone", "phon" },
			{ "brassbell", "bell" },
			{ "vtypeengine", "vte" },
			{ "doublebarrelshotgun", "dbsg" },
			{ "yieldsign", "yie" },
			{ "stopsign", "sto" },
			{ "largeaxle", "lar" },
			{ "tatteredmetalsheet", "tat" },
			{ "diyflashbang", "diy" },
			{ "whoopiecushion", "who" },
			{ "jarchofpickles", "jar" },
			{ "jarofpickles", "jar" },
			{ "cashregister", "cas" },
			{ "apparatus", "app" }
		};

		private static readonly HashSet<string> SpecialOrSystemScrapNormalizedNames = new HashSet<string> { "apparatus", "key", "keys", "beehive", "hive", "shotgun", "doublebarrelshotgun", "shotgunshells", "knife" };

		private static readonly int[] BoundsBoxTriangleTemplate = BuildBoundsBoxTriangleTemplate();

		private static readonly string[] ManeaterDiagnosticKeywords = new string[19]
		{
			"attack", "kill", "charge", "lunge", "eat", "eating", "maul", "grab", "held", "hold",
			"target", "player", "animation", "state", "baby", "anger", "rage", "cooldown", "timer"
		};

		private static readonly Dictionary<int, float> DogAnimationCalculationNextTimes = new Dictionary<int, float>();

		private static readonly string[] MaskedDiagnosticKeywords = new string[11]
		{
			"kill", "animation", "player", "target", "special", "coroutine", "cooldown", "stun", "chase", "mimic",
			"mask"
		};

		internal static bool DiagnosticsEnabled => false;

		internal static void LogFeatureContractDiagnostics()
		{
			try
			{
				string[] value = new string[4]
				{
					DescribeRuntimeMemberContract("RedLocustBees", new string[4] { "hive", "hasSpawnedHive", "lastKnownHivePosition", "syncedLastKnownHivePosition" }),
					DescribeRuntimeMemberContract("GiantKiwiAI", new string[7] { "birdNest", "birdNestPrefab", "eggPrefab", "eggs", "hasSpawnedEggs", "nestPosition", "newNestPosition" }),
					DescribeRuntimeMemberContract(typeof(PlayerControllerB).FullName, new string[4] { "health", "sprintMeter", "sprintMeterUI", "isPlayerControlled" }),
					DescribeRuntimeMemberContract(typeof(Terminal).FullName, new string[2] { "screenText", "textAdded" })
				};
				string text = string.Join(" || ", value);
				Plugin.Log.LogInfo((object)("[DllContract] " + text));
			}
			catch (Exception ex)
			{
				string text2 = "contract diagnostic failed " + ex.GetType().Name + ":" + ex.Message;
				Plugin.Log.LogWarning((object)("[DllContract] " + text2));
			}
		}

		private static string DescribeRuntimeMemberContract(string typeName, IEnumerable<string> memberNames)
		{
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				return typeName + "=<TYPE NOT FOUND>";
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			List<string> list = new List<string>();
			foreach (string memberName in memberNames)
			{
				FieldInfo field = type.GetField(memberName, bindingAttr);
				if (field != null)
				{
					list.Add(memberName + ":field:" + field.FieldType.FullName);
					continue;
				}
				PropertyInfo property = type.GetProperty(memberName, bindingAttr);
				if (property != null)
				{
					list.Add(memberName + ":property:" + property.PropertyType.FullName);
				}
				else
				{
					list.Add(memberName + ":MISSING");
				}
			}
			return type.FullName + "[" + string.Join(",", list) + "]";
		}

		internal static void RuntimeFrameTick(string source)
		{
			int frameCount = Time.frameCount;
			if (lastRuntimeFrameTick == frameCount)
			{
				return;
			}
			lastRuntimeFrameTick = frameCount;
			lastRuntimeDriverSource = (string.IsNullOrWhiteSpace(source) ? "unknown" : source);
			try
			{
				PluginVisualTick();
				PluginFastBoundaryTick();
				PluginTick();
				UpdatePracticeStatsHud(forceLog: false);
			}
			catch (Exception ex)
			{
				string text = "RuntimeFrameTick EXCEPTION source=" + lastRuntimeDriverSource + " " + ex.GetType().Name + ":" + ex.Message;
				Plugin.Log.LogWarning((object)("[RuntimeTick] " + text));
			}
		}

		internal static void PluginTick()
		{
			if (!PracticeActive)
			{
				return;
			}
			ResolvePendingSpecialSpawnGroupsIfNeeded();
			ProcessPendingGiantKiwiHomeRestores();
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null)
			{
				TryRescueInvinciblePlayerFromAbyss(val);
			}
			MaintainLocalPlayerInvincibleFastIfEnabled();
			ProcessPendingLocalPlayerRescue();
			ProcessPendingBushWolfPostRescueResets();
			ProcessPendingMaskedKillResets();
			ApplyCriticalVisualHealthGate();
			MaintainPracticePlayerFacilityFlags();
			MaintainShipTerminalInteraction();
			SuppressEnemyAwarenessIfPlayerOutsideRedArea();
			if (!(Time.realtimeSinceStartup < nextRuntimeTickTime))
			{
				nextRuntimeTickTime = Time.realtimeSinceStartup + 0.25f;
				if (Time.realtimeSinceStartup < localPlayerPostHealCleanupUntilTime)
				{
					CleanupLocalPlayerAfterFullHeal();
				}
				KeepEnemiesInsideEnemyArea();
				MaintainSpecialEnemyPracticeBehaviour();
				MaintainPendingBaboonHawkGrouping();
				MaintainPracticeInitialLooseItemCleanup();
				KeepLocalPlayerAliveButNotAlwaysHealed();
				MaintainLocalPlayerInvincibleIfEnabled();
				if (Time.realtimeSinceStartup >= nextNoonTimeForceTime)
				{
					nextNoonTimeForceTime = Time.realtimeSinceStartup + 1f;
					ForcePracticeTimeNoon();
				}
				if (Time.realtimeSinceStartup >= nextEnemyRescanTime)
				{
					nextEnemyRescanTime = Time.realtimeSinceStartup + 5f;
					RefreshEnemyTracking(force: false);
					RefreshEnemyBoundaryWallCollisionIgnores("periodic refresh");
				}
				if (lateWorldCleanupPending && Time.realtimeSinceStartup >= lateWorldCleanupDueTime)
				{
					lateWorldCleanupPending = false;
					DisableExistingMapVisualsAndColliders();
					DisableVanillaPracticeVisualRoots(includeGeneratedDungeon: true, "delayed post-generation cleanup");
					nextTerminalInteractionRepairTime = 0f;
					MaintainShipTerminalInteraction();
					Plugin.Log.LogInfo((object)"[WorldCleanup] Completed one delayed post-generation cleanup pass including generated-root deactivation.");
				}
				if (!ArenaCreated && Time.realtimeSinceStartup >= arenaCreationAllowedTime)
				{
					TryCreatePracticeArenaSafely("PluginTick delayed creation", ignoreDelay: false, clearOldArena: true);
				}
				if (Time.realtimeSinceStartup >= nextSlowTickTime)
				{
					nextSlowTickTime = Time.realtimeSinceStartup + 0.75f;
					RescueLocalPlayerIfNeeded();
				}
			}
		}

		internal static bool HandleUnityDebugLog(object message)
		{
			if (!PracticeActive || message == null)
			{
				return true;
			}
			string text = message.ToString() ?? "";
			if (!string.Equals(text.Trim(), "Path to exit could not be calculated", StringComparison.Ordinal))
			{
				return true;
			}
			return false;
		}

		internal static string Normalize(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return "";
			}
			string input = text.ToLowerInvariant();
			return Regex.Replace(input, "[^a-z0-9]", "");
		}

		internal static bool ShouldForcePlayerTargetable(EnemyAI enemy, PlayerControllerB player)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (!PracticeActive || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (player.isPlayerDead)
			{
				return false;
			}
			if (ShouldHidePlayerFromPracticeEnemy(enemy, player))
			{
				return false;
			}
			if (!ArenaCreated)
			{
				return true;
			}
			Vector3 position = ((Component)player).transform.position;
			float num = Vector3.Distance(new Vector3(position.x, 0f, position.z), new Vector3(PracticeAreaCenter.x, 0f, PracticeAreaCenter.z));
			return num <= 140f;
		}

		internal static bool ShouldHidePlayerFromPracticeEnemy(EnemyAI enemy, PlayerControllerB player)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (!PracticeActive || !ArenaCreated || !HidePlayersOutsideEnemyAreaFromEnemies || (Object)(object)enemy == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (player.isPlayerDead)
			{
				return false;
			}
			if (!IsPointInsideEnemyArea(((Component)enemy).transform.position, 1f))
			{
				return false;
			}
			return !IsPointInsideEnemyArea(((Component)player).transform.position, 0.15f);
		}

		private static bool IsPointInsideEnemyArea(Vector3 position, float margin)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!ArenaCreated)
			{
				return false;
			}
			Vector3 val = position - EnemyAreaCenter;
			float num = Vector3.Dot(val, EnemyAreaRight);
			float num2 = Vector3.Dot(val, EnemyAreaForward);
			float num3 = EnemyAreaHalfSize + margin;
			return num >= 0f - num3 && num <= num3 && num2 >= 0f - num3 && num2 <= num3;
		}

		private static bool IsPointInsidePracticePlatform(Vector3 position, float margin)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!ArenaCreated)
			{
				return false;
			}
			Vector3 val = position - PracticeAreaCenter;
			float num = Vector3.Dot(val, EnemyAreaRight);
			float num2 = Vector3.Dot(val, EnemyAreaForward);
			float num3 = PracticeAreaHalfSize + margin;
			bool flag = num >= 0f - num3 && num <= num3 && num2 >= 0f - num3 && num2 <= num3;
			bool flag2 = Mathf.Abs(position.y - GetEnemyFloorY()) <= 5f;
			return flag && flag2;
		}

		private static void MaintainPracticePlayerFacilityFlags()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup < nextPlayerFacilityFlagTime)
			{
				return;
			}
			nextPlayerFacilityFlagTime = realtimeSinceStartup + 0.25f;
			if (!PracticeActive || !ArenaCreated)
			{
				return;
			}
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && IsPointInsideEnemyArea(((Component)val).transform.position, 1.5f))
				{
					SetBoolFieldIfExists(val, "isInsideFactory", value: true);
					SetBoolFieldIfExists(val, "isInHangarShipRoom", value: false);
					SetBoolFieldIfExists(val, "isInsidePlayerShip", value: false);
				}
			}
			catch
			{
			}
		}

		private static void AddShipTerminalHierarchyToProtectionCache(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			try
			{
				Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
					{
						ShipTerminalProtectedObjectIds.Add(((Object)((Component)val).gameObject).GetInstanceID());
					}
				}
			}
			catch
			{
			}
		}

		private static void RefreshShipTerminalProtectionCache()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			ShipTerminalProtectedObjectIds.Clear();
			try
			{
				Terminal[] array = Resources.FindObjectsOfTypeAll<Terminal>();
				foreach (Terminal val in array)
				{
					if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
					{
						continue;
					}
					Scene scene = ((Component)val).gameObject.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						continue;
					}
					scene = ((Component)val).gameObject.scene;
					if (!((Scene)(ref scene)).isLoaded)
					{
						continue;
					}
					AddShipTerminalHierarchyToProtectionCache(((Component)val).gameObject);
					object fieldOrPropertyValue = GetFieldOrPropertyValue(val, "terminalTrigger");
					Component val2 = (Component)((fieldOrPropertyValue is Component) ? fieldOrPropertyValue : null);
					if (val2 != null && (Object)(object)val2.gameObject != (Object)null)
					{
						AddShipTerminalHierarchyToProtectionCache(val2.gameObject);
						continue;
					}
					GameObject val3 = (GameObject)((fieldOrPropertyValue is GameObject) ? fieldOrPropertyValue : null);
					if (val3 != null)
					{
						AddShipTerminalHierarchyToProtectionCache(val3);
					}
				}
			}
			catch
			{
			}
		}

		private static void MaintainShipTerminalInteraction()
		{
			if (!PracticeActive)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup < nextTerminalInteractionRepairTime)
			{
				return;
			}
			nextTerminalInteractionRepairTime = realtimeSinceStartup + 0.5f;
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val != (Object)null && val.inTerminalMenu)
				{
					return;
				}
				Terminal val2 = ((IEnumerable<Terminal>)Resources.FindObjectsOfTypeAll<Terminal>()).FirstOrDefault((Func<Terminal, bool>)delegate(Terminal candidate)
				{
					//IL_001d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0022: Unknown result type (might be due to invalid IL or missing references)
					//IL_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)
					int result;
					if ((Object)(object)candidate != (Object)null && (Object)(object)((Component)candidate).gameObject != (Object)null)
					{
						Scene scene = ((Component)candidate).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							scene = ((Component)candidate).gameObject.scene;
							result = (((Scene)(ref scene)).isLoaded ? 1 : 0);
							goto IL_0042;
						}
					}
					result = 0;
					goto IL_0042;
					IL_0042:
					return (byte)result != 0;
				});
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				if (ShipTerminalProtectedObjectIds.Count == 0)
				{
					RefreshShipTerminalProtectionCache();
				}
				if (!((Component)val2).gameObject.activeSelf)
				{
					((Component)val2).gameObject.SetActive(true);
				}
				if (!((Behaviour)val2).enabled)
				{
					((Behaviour)val2).enabled = true;
				}
				object fieldOrPropertyValue = GetFieldOrPropertyValue(val2, "terminalTrigger");
				Component val3 = (Component)((fieldOrPropertyValue is Component) ? fieldOrPropertyValue : null);
				GameObject val4 = (GameObject)(((Object)(object)val3 != (Object)null) ? val3.gameObject : ((fieldOrPropertyValue is GameObject) ? fieldOrPropertyValue : null));
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
				if (!val4.activeSelf)
				{
					val4.SetActive(true);
				}
				Behaviour val5 = (Behaviour)(object)((val3 is Behaviour) ? val3 : null);
				if (val5 != null && !val5.enabled)
				{
					val5.enabled = true;
				}
				SetFieldOrPropertyValue(fieldOrPropertyValue, "interactable", true);
				Collider[] componentsInChildren = val4.GetComponentsInChildren<Collider>(true);
				foreach (Collider val6 in componentsInChildren)
				{
					if ((Object)(object)val6 != (Object)null && !val6.enabled)
					{
						val6.enabled = true;
					}
				}
			}
			catch
			{
			}
		}

		internal static void PluginUpdateDiagnosticHeartbeat(string source)
		{
		}

		private static void LogArenaDiagnosticState(string context)
		{
			bool flag = true;
		}

		private static bool ShouldLogGlobalDiagnostic(ref float nextTime, float intervalSeconds)
		{
			bool flag = true;
			return false;
		}

		private static bool ShouldLogEnemyDiagnostic(int instanceId, float intervalSeconds)
		{
			bool flag = true;
			return false;
		}

		private static string FormatVector3(Vector3 value)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			return $"({value.x:F2},{value.y:F2},{value.z:F2})";
		}

		internal static void QueuePracticeRoute()
		{
			PracticeQueued = true;
			SelectableLevel val = FindFallbackLevel();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not find a fallback moon for practice.");
				return;
			}
			try
			{
				Terminal val2 = Object.FindObjectOfType<Terminal>();
				int num = (((Object)(object)val2 != (Object)null) ? val2.groupCredits : 0);
				StartOfRound.Instance.ChangeLevelServerRpc(val.levelID, num);
				Plugin.Log.LogInfo((object)$"Practice route queued. Fallback level id: {val.levelID}, planet: {val.PlanetName}");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to route to practice fallback level: {arg}");
			}
		}

		private static SelectableLevel? FindFallbackLevel()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.levels == null || StartOfRound.Instance.levels.Length == 0)
			{
				return null;
			}
			SelectableLevel val = ((IEnumerable<SelectableLevel>)StartOfRound.Instance.levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => (Object)(object)level != (Object)null && Normalize(level.PlanetName).Contains("experimentation")));
			return val ?? ((IEnumerable<SelectableLevel>)StartOfRound.Instance.levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => (Object)(object)level != (Object)null));
		}

		internal static void ApplyPracticeLevelSettings(SelectableLevel newLevel)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			if (PracticeQueued)
			{
				PracticeQueued = false;
				PracticeActive = true;
				Plugin.Log.LogInfo((object)$"[Session] PracticeActive=TRUE levelId={newLevel.levelID} planet={newLevel.PlanetName}");
				ArenaCreated = false;
				SpawnedEnemies.Clear();
				PracticeSpawnedUtilityObjects.Clear();
				ClearPracticeSpecialSessionState(destroyStructural: false, "ApplyPracticeLevelSettings begin");
				PracticeStatsOverlayEnabled = true;
				practiceStatsLastRenderedText = "";
				PracticeHitboxOverlayEnabled = false;
				statsOverlayFirstDrawLogged = false;
				nextStatsOverlayDiagTime = 0f;
				nextHitboxRuntimeDiagTime = 0f;
				hitboxRefreshDirty = false;
				hitboxDirtyReason = "session-reset";
				nextHitboxTransformUpdateTime = 0f;
				nextHitboxPlayerRosterCheckTime = 0f;
				lastHitboxRemotePlayerCount = -1;
				nextSpecialLootVisualUpdateTime = 0f;
				nextFastBoundaryTickTime = 0f;
				nextPlayerFacilityFlagTime = 0f;
				nextAwarenessFastTickTime = 0f;
				nextStatsHudDiagTime = 0f;
				nextStatsHudUpdateTime = 0f;
				practiceStatsFixedPositionCaptured = false;
				practiceStatsFixedAnchoredPosition = new Vector2(210f, -70f);
				statsHudCreatedLogged = false;
				lastRuntimeFrameTick = -1;
				nextRuntimeDriverDiagTime = 0f;
				lastRuntimeDriverSource = "session-start";
				lastCriticalGateObservedHealth = -1;
				lastCriticalGateObservedCritical = false;
				criticalVisualClearAppliedForHealthyState = false;
				ClearPracticeStatsHud("ApplyPracticeLevelSettings begin");
				PracticeGiantKiwiNestTargets.Clear();
				PracticeGiantKiwiNestOverrideLoggedIds.Clear();
				PracticeGiantKiwiNestOriginalPositions.Clear();
				PracticeGiantKiwiNestMoveDeltas.Clear();
				PracticeGiantKiwiNestRelocatedIds.Clear();
				PracticeGiantKiwiEggRelocatedIds.Clear();
				PracticeGiantKiwiHomePositions.Clear();
				PracticeGiantKiwiHomeRestoreDueTimes.Clear();
				PracticeGiantKiwiHomeRestoreLoggedIds.Clear();
				PracticeGiantKiwiKillStackLoggedIds.Clear();
				PracticeManualMoldGenerationInProgress = false;
				nextInvAbyssRescueAllowedTime = 0f;
				EnemyBarrierPushCooldown.Clear();
				JesterPracticePoppedIds.Clear();
				JesterPracticeNoResetArmedIds.Clear();
				JesterPracticePreCrankIds.Clear();
				JesterInitializationSeenIds.Clear();
				JesterCrankStartedIds.Clear();
				JesterSequenceNextDiagTimes.Clear();
				JesterMethodInventoryLoggedIds.Clear();
				MouthDogDirectLungeNextTimes.Clear();
				DogDeepDiagNextTimes.Clear();
				DogMethodInventoryLoggedIds.Clear();
				ForcedAdultManeaterIds.Clear();
				ManeaterRecoveryUntilTimes.Clear();
				ManeaterDeepDiagNextTimes.Clear();
				ManeaterMethodInventoryLoggedIds.Clear();
				ManeaterDeferredResetIds.Clear();
				ManeaterResetInProgressIds.Clear();
				ManeaterDeferredResetReasons.Clear();
				OldBirdDiagNextTimes.Clear();
				OldBirdMethodInventoryLoggedIds.Clear();
				OldBirdWakeAttemptedIds.Clear();
				OldBirdThreatEventNextLogTimes.Clear();
				GiantKiwiThreatEventNextLogTimes.Clear();
				OldBirdThreatSnapshotNextTimes.Clear();
				OldBirdThreatCapabilityByEnemyId.Clear();
				OldBirdNonPlayerThreatSeenSince.Clear();
				OldBirdEntityAlertAssistCooldownUntil.Clear();
				OldBirdEntityAttackSeenSince.Clear();
				OldBirdEntityAttackAssistCooldownUntil.Clear();
				OldBirdDeepDiagNextTimes.Clear();
				BushWolfPostRescueResetDueTimes.Clear();
				BushWolfPostRescueResetAttempts.Clear();
				BushWolfOriginalBaseOffsets.Clear();
				BushWolfGrowlCounts.Clear();
				BushWolfGrowlLastTimes.Clear();
				BrackenMemberInventoryLoggedIds.Clear();
				BrackenLastBehaviourStateById.Clear();
				BrackenLastStateLogTimeById.Clear();
				baboonGroupRefreshPending = false;
				baboonGroupRefreshAt = 0f;
				baboonGroupLastSignature = "";
				PracticeBaboonCampObject = null;
				practiceAmbientEffectsDisabled = false;
				PracticeManuallySpawnedItemIds.Clear();
				PendingFoxGrassObjects.Clear();
				PendingFoxGrassCenter = Vector3.zero;
				ambientSourceInventoryLogged = false;
				initialLooseItemCleanupDone = false;
				initialLooseItemCleanupAt = 0f;
				ForestGiantDiagNextTimes.Clear();
				ForestGiantMethodInventoryLoggedIds.Clear();
				EnemyPostSpawnIdentityLoggedIds.Clear();
				DogKeywordMethodInventoryLoggedIds.Clear();
				OldBirdKeywordMethodInventoryLoggedIds.Clear();
				ForestGiantKeywordMethodInventoryLoggedIds.Clear();
				ForestGiantZeroAnimatorMotionFrames.Clear();
				ForestGiantAnimatorFixNextLogTimes.Clear();
				TulipBoundaryGuardNextTimes.Clear();
				pendingLocalPlayerRescueScheduled = false;
				pendingLocalPlayerRescueTime = 0f;
				pendingLocalPlayerRescueReason = "";
				nextAwarenessSuppressionTime = 0f;
				nextRuntimeTickTime = 0f;
				nextSlowTickTime = 0f;
				nextEnemyRescanTime = 0f;
				nextArenaAttemptTime = 0f;
				arenaCreationAllowedTime = Time.realtimeSinceStartup + 5f;
				lateWorldCleanupDueTime = 0f;
				lateWorldCleanupPending = false;
				nextNoonTimeForceTime = 0f;
				localPlayerPostHealCleanupUntilTime = 0f;
				nextInvincibleDetailedDiagTime = 0f;
				lastInvincibleObservedDeadState = false;
				invincibleFieldInventoryLogged = false;
				nextCriticalVisualHealthGateTime = 0f;
				roundManagerRefreshAttempted = false;
				itemCacheDirty = true;
				nextPluginUpdateDiagnosticTime = 0f;
				nextArenaDiagnosticLogTime = 0f;
				nextNavMeshDiagnosticLogTime = 0f;
				nextEnemySummaryDiagnosticTime = 0f;
				EnemyDiagnosticNextLogTimes.Clear();
				floorPostProcessingArenaAttempted = false;
				Plugin.Log.LogInfo((object)"Applying practice moon settings.");
				LogArenaDiagnosticState("ApplyPracticeLevelSettings initialized");
				Plugin.Log.LogInfo((object)"Practice arena creation requested. Existing terrain/map visuals/colliders will be disabled.");
				Plugin.Log.LogInfo((object)"Use the default in-game chat (Enter or /) for practice quick commands such as mas3 / sho2 / shot / heal / god.");
				Plugin.Log.LogInfo((object)"Practice commands are available directly in chat or the ship Terminal while Practice is active.");
				newLevel.PlanetName = "practice";
				ForceWeatherNone(newLevel);
				DisablePracticeWeatherAndAmbientEffects("ApplyPracticeLevelSettings");
				if (newLevel.Enemies != null)
				{
					newLevel.Enemies.Clear();
				}
				if (newLevel.OutsideEnemies != null)
				{
					newLevel.OutsideEnemies.Clear();
				}
				if (newLevel.DaytimeEnemies != null)
				{
					newLevel.DaytimeEnemies.Clear();
				}
				SetIntFieldIfExists(newLevel, "maxEnemyPowerCount", 0);
				SetIntFieldIfExists(newLevel, "maxOutsideEnemyPowerCount", 0);
				SetIntFieldIfExists(newLevel, "maxDaytimeEnemyPowerCount", 0);
				try
				{
					newLevel.minScrap = 0;
					newLevel.maxScrap = 0;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Failed to set scrap settings: " + ex.Message));
				}
				ForcePracticeTimeNoon();
				Plugin.Log.LogInfo((object)"Practice moon settings applied. Planet name: practice. Weather: None. Natural enemies disabled. Natural scrap spawn is blocked by SpawnScrapInLevel prefix.");
			}
		}

		private static void ForceWeatherNone(SelectableLevel level)
		{
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = typeof(SelectableLevel).GetField("currentWeather", bindingAttr);
				if (field != null && field.FieldType.IsEnum)
				{
					object value = Enum.Parse(field.FieldType, "None", ignoreCase: true);
					field.SetValue(level, value);
					Plugin.Log.LogInfo((object)"Practice weather forced to None by field.");
					return;
				}
				PropertyInfo property = typeof(SelectableLevel).GetProperty("currentWeather", bindingAttr);
				if (property != null && property.CanWrite && property.PropertyType.IsEnum)
				{
					object value2 = Enum.Parse(property.PropertyType, "None", ignoreCase: true);
					property.SetValue(level, value2);
					Plugin.Log.LogInfo((object)"Practice weather forced to None by property.");
				}
				else
				{
					Plugin.Log.LogWarning((object)"Could not find SelectableLevel.currentWeather field/property.");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to force weather to None: " + ex.Message));
			}
		}

		private static void DisablePracticeWeatherAndAmbientEffects(string context)
		{
			if (!PracticeActive)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			bool flag = false;
			try
			{
				if ((Object)(object)TimeOfDay.Instance != (Object)null)
				{
					MethodInfo methodInfo = ((object)TimeOfDay.Instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => string.Equals(m.Name, "DisableAllWeather", StringComparison.Ordinal));
					if (methodInfo != null)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						object[] parameters2 = ((parameters.Length != 1 || !(parameters[0].ParameterType == typeof(bool))) ? Array.Empty<object>() : new object[1] { true });
						methodInfo.Invoke(TimeOfDay.Instance, parameters2);
						flag = true;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[AmbientDiag] DisableAllWeather failed. context=" + context + " error=" + ex.GetType().Name + ": " + ex.Message));
			}
			try
			{
				ParticleSystem[] array = Object.FindObjectsOfType<ParticleSystem>(true);
				foreach (ParticleSystem val in array)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val).gameObject))
					{
						try
						{
							val.Stop(true, (ParticleSystemStopBehavior)0);
							num++;
						}
						catch
						{
						}
					}
				}
				Type type = AccessTools.TypeByName("UnityEngine.VFX.VisualEffect");
				if (type != null)
				{
					Object[] array2 = Object.FindObjectsOfType(type, true);
					foreach (Object val2 in array2)
					{
						Component val3 = (Component)(object)((val2 is Component) ? val2 : null);
						if ((Object)(object)val3 == (Object)null || (Object)(object)val3.gameObject == (Object)null || !ShouldDisableWorldObject(val3.gameObject))
						{
							continue;
						}
						try
						{
							InvokeMethodIfExists(val3, "Stop");
							Behaviour val4 = (Behaviour)(object)((val3 is Behaviour) ? val3 : null);
							if (val4 != null)
							{
								val4.enabled = false;
							}
							num2++;
						}
						catch
						{
						}
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[AmbientDiag] ambient effect cleanup failed. context=" + context + " error=" + ex2.GetType().Name + ": " + ex2.Message));
			}
			int num5 = DisablePracticeLocalVolumetricFogObjects();
			if (!practiceAmbientEffectsDisabled || num > 0 || num2 > 0 || num5 > 0)
			{
				Plugin.Log.LogInfo((object)$"[AmbientDiag] context={context} DisableAllWeather={flag} stoppedParticles={num} disabledVisualEffects={num2} disabledLocalVolumetricFog={num5}");
			}
			practiceAmbientEffectsDisabled = true;
		}

		private static int DisablePracticeLocalVolumetricFogObjects()
		{
			int num = 0;
			try
			{
				GameObject[] array = Object.FindObjectsOfType<GameObject>(true);
				foreach (GameObject val in array)
				{
					if ((Object)(object)val == (Object)null || !ShouldDisableWorldObject(val))
					{
						continue;
					}
					string text = GetHierarchyPath(val).ToLowerInvariant();
					if (text.Contains("fogexclusion"))
					{
						continue;
					}
					Component[] components = val.GetComponents<Component>();
					foreach (Component val2 in components)
					{
						if ((Object)(object)val2 == (Object)null || !string.Equals(((object)val2).GetType().Name, "LocalVolumetricFog", StringComparison.Ordinal))
						{
							continue;
						}
						try
						{
							bool flag = false;
							Behaviour val3 = (Behaviour)(object)((val2 is Behaviour) ? val2 : null);
							if (val3 != null && val3.enabled)
							{
								val3.enabled = false;
								flag = true;
							}
							if (flag)
							{
								num++;
								Plugin.Log.LogInfo((object)("[AmbientDiag][FOG-OFF] path=" + GetHierarchyPath(val) + " type=" + ((object)val2).GetType().FullName));
							}
						}
						catch
						{
						}
					}
					if ((text.Contains("/duststorm") || text.EndsWith("duststorm") || text.Contains("localrollingfog")) && val.activeSelf)
					{
						try
						{
							val.SetActive(false);
						}
						catch
						{
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[AmbientDiag][FOG-OFF] failed: " + ex.GetType().Name + ": " + ex.Message));
			}
			return num;
		}

		private static int DisableDustCloudObjects()
		{
			int num = 0;
			try
			{
				Type type = AccessTools.TypeByName("DustClouds");
				if (type == null)
				{
					return 0;
				}
				Object[] array = Object.FindObjectsOfType(type, true);
				foreach (Object val in array)
				{
					Component val2 = (Component)(object)((val is Component) ? val : null);
					if ((Object)(object)val2 == (Object)null || (Object)(object)val2.gameObject == (Object)null || !ShouldDisableWorldObject(val2.gameObject))
					{
						continue;
					}
					try
					{
						Behaviour val3 = (Behaviour)(object)((val2 is Behaviour) ? val2 : null);
						if (val3 != null)
						{
							val3.enabled = false;
						}
						val2.gameObject.SetActive(false);
						num++;
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			return num;
		}

		private static void LogAmbientSourceInventoryOnce(string context)
		{
			if (ambientSourceInventoryLogged)
			{
				return;
			}
			ambientSourceInventoryLogged = true;
			try
			{
				List<string> list = new List<string>();
				GameObject[] array = Object.FindObjectsOfType<GameObject>(true);
				foreach (GameObject val in array)
				{
					if ((Object)(object)val == (Object)null || !ShouldDisableWorldObject(val))
					{
						continue;
					}
					string text = Normalize(((Object)val).name);
					if (text.Contains("wind") || text.Contains("dust") || text.Contains("cloud") || text.Contains("fog") || text.Contains("weather"))
					{
						string arg = string.Join(",", (from c in val.GetComponents<Component>()
							where (Object)(object)c != (Object)null
							select ((object)c).GetType().Name).Distinct().Take(16));
						list.Add($"{GetHierarchyPath(val)} [{arg}] active={val.activeInHierarchy}");
						if (list.Count >= 80)
						{
							break;
						}
					}
				}
				Plugin.Log.LogInfo((object)("[AmbientSourceDiag] context=" + context + " candidates=" + ((list.Count == 0) ? "<none>" : string.Join(" || ", list))));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[AmbientSourceDiag] inventory failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static void ForcePracticeTimeNoon()
		{
			try
			{
				if (!((Object)(object)TimeOfDay.Instance == (Object)null))
				{
					object instance = TimeOfDay.Instance;
					float floatFieldOrDefault = GetFloatFieldOrDefault(instance, "totalTime", 1080f);
					float num = floatFieldOrDefault * 0.25f;
					SetFloatFieldIfExists(instance, "globalTime", num);
					SetFloatFieldIfExists(instance, "currentDayTime", num);
					SetFloatFieldIfExists(instance, "normalizedTimeOfDay", 0.25f);
					SetFloatFieldIfExists(instance, "timeUntilDeadline", floatFieldOrDefault - num);
					SetFloatFieldIfExists(instance, "globalTimeAtStartOfDay", num);
					SetBoolFieldIfExists(instance, "currentDayTimeStarted", value: false);
					ForcePracticeSunNoonVisual();
				}
			}
			catch
			{
			}
		}

		private static void ForcePracticeSunNoonVisual()
		{
			if (!PracticeActive || (Object)(object)TimeOfDay.Instance == (Object)null)
			{
				return;
			}
			try
			{
				object? fieldOrPropertyValue = GetFieldOrPropertyValue(TimeOfDay.Instance, "sunAnimator");
				Animator val = (Animator)((fieldOrPropertyValue is Animator) ? fieldOrPropertyValue : null);
				if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled)
				{
					val.SetFloat("timeOfDay", 1f / 3f);
				}
			}
			catch
			{
			}
		}

		private static float GetFloatFieldOrDefault(object target, string fieldName, float fallback)
		{
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = target.GetType().GetField(fieldName, bindingAttr);
				if (field != null && field.FieldType == typeof(float))
				{
					return (float)field.GetValue(target);
				}
			}
			catch
			{
			}
			return fallback;
		}

		private static void SetFloatFieldIfExists(object target, string fieldName, float value)
		{
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = target.GetType().GetField(fieldName, bindingAttr);
				if (field != null && field.FieldType == typeof(float))
				{
					field.SetValue(target, value);
				}
			}
			catch
			{
			}
		}

		private static void SetIntFieldIfExists(object target, string fieldName, int value)
		{
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = target.GetType().GetField(fieldName, bindingAttr);
				if (field != null && field.FieldType == typeof(int))
				{
					field.SetValue(target, value);
					Plugin.Log.LogInfo((object)$"Set {fieldName} to {value}.");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to set " + fieldName + ": " + ex.Message));
			}
		}

		private static void SetBoolFieldIfExists(object target, string fieldName, bool value)
		{
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = target.GetType().GetField(fieldName, bindingAttr);
				if (field != null && field.FieldType == typeof(bool))
				{
					field.SetValue(target, value);
				}
			}
			catch
			{
			}
		}

		private static void SetVector3FieldIfExists(object target, string fieldName, Vector3 value)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
				FieldInfo field = target.GetType().GetField(fieldName, bindingAttr);
				if (field != null && field.FieldType == typeof(Vector3))
				{
					field.SetValue(target, value);
				}
			}
			catch
			{
			}
		}

		private static void DisableExistingMapVisualsAndColliders()
		{
			RefreshShipTerminalProtectionCache();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			Terrain[] array = Object.FindObjectsOfType<Terrain>(true);
			foreach (Terrain val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val).gameObject) && ((Behaviour)val).enabled)
				{
					((Behaviour)val).enabled = false;
					DisabledTerrains.Add(val);
					num3++;
				}
			}
			Renderer[] array2 = Object.FindObjectsOfType<Renderer>(true);
			foreach (Renderer val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val2).gameObject))
				{
					SetRendererForceRenderingOffBestEffort(val2, value: true);
					if (val2.enabled)
					{
						val2.enabled = false;
						DisabledMapRenderers.Add(val2);
						num++;
					}
				}
			}
			Collider[] array3 = Object.FindObjectsOfType<Collider>(true);
			foreach (Collider val3 in array3)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val3).gameObject) && val3.enabled)
				{
					val3.enabled = false;
					DisabledMapColliders.Add(val3);
					num2++;
				}
			}
			int num4 = 0;
			try
			{
				LODGroup[] array4 = Object.FindObjectsOfType<LODGroup>(true);
				bool flag = default(bool);
				foreach (LODGroup val4 in array4)
				{
					if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).gameObject == (Object)null || !ShouldDisableWorldObject(((Component)val4).gameObject))
					{
						continue;
					}
					PropertyInfo property = ((object)val4).GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
					if (property != null && property.CanWrite)
					{
						object value = property.GetValue(val4, null);
						int num5;
						if (value is bool)
						{
							flag = (bool)value;
							num5 = ((1 == 0) ? 1 : 0);
						}
						else
						{
							num5 = 1;
						}
						if (((uint)num5 | (flag ? 1u : 0u)) != 0)
						{
							property.SetValue(val4, false, null);
							num4++;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[WorldCleanup] LODGroup disable pass failed: " + ex.GetType().Name + ": " + ex.Message));
			}
			DisableVanillaPracticeVisualRoots(includeGeneratedDungeon: false, "world cleanup");
			DisablePracticeWeatherAndAmbientEffects("world cleanup");
			nextTerminalInteractionRepairTime = 0f;
			MaintainShipTerminalInteraction();
			int num6 = num + num2 + num3 + num4;
			if (num6 > 0)
			{
				Plugin.Log.LogInfo((object)$"Disabled existing terrain/map visuals/colliders. Terrains: {num3}, Renderers: {num}, Colliders: {num2}, LODGroups: {num4}");
			}
		}

		private static void SetRendererForceRenderingOffBestEffort(Renderer renderer, bool value)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return;
			}
			try
			{
				PropertyInfo property = typeof(Renderer).GetProperty("forceRenderingOff", BindingFlags.Instance | BindingFlags.Public);
				if (property != null && property.CanWrite)
				{
					property.SetValue(renderer, value, null);
				}
			}
			catch
			{
			}
		}

		private static void DisableVanillaPracticeVisualRoots(bool includeGeneratedDungeon, string context)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				foreach (GameObject val in array)
				{
					if ((Object)(object)val == (Object)null || IsPracticeObject(val))
					{
						continue;
					}
					Scene scene = val.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						continue;
					}
					scene = val.scene;
					if (((Scene)(ref scene)).isLoaded)
					{
						string text = GetHierarchyPath(val).Replace('\\', '/').ToLowerInvariant();
						bool flag = text == "environment/map/modelsintroscene" || text.EndsWith("/environment/map/modelsintroscene");
						bool flag2 = includeGeneratedDungeon && (text == "systems/levelgeneration/levelgenerationroot" || text.EndsWith("/systems/levelgeneration/levelgenerationroot"));
						if ((flag || flag2) && val.activeSelf)
						{
							val.SetActive(false);
							num++;
							Plugin.Log.LogInfo((object)("[WorldCleanup][ROOT-OFF] context=" + context + " path=" + GetHierarchyPath(val)));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[WorldCleanup][ROOT-OFF-ERROR] context=" + context + " " + ex.GetType().Name + ": " + ex.Message));
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"[WorldCleanup][ROOT-OFF] context={context} disabledRoots={num}");
			}
		}

		private static bool ShouldDisableWorldObject(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			if (IsPracticeObject(obj))
			{
				return false;
			}
			if (ShipTerminalProtectedObjectIds.Contains(((Object)obj).GetInstanceID()))
			{
				return false;
			}
			string text = GetHierarchyPath(obj).ToLowerInvariant();
			string text2 = Normalize(((Object)obj).name ?? "");
			if (text.Contains("hangarship"))
			{
				return false;
			}
			if (text.Contains("player"))
			{
				return false;
			}
			if (text.Contains("terminalscript"))
			{
				return false;
			}
			if (text.Contains("startofround") || text.Contains("roundmanager") || text.Contains("networkmanager"))
			{
				return false;
			}
			if (text.Contains("hudmanager") || text.Contains("systems/ui") || text.Contains("mapcamera"))
			{
				return false;
			}
			if (text.StartsWith("environment/") && !text.Contains("hangarship"))
			{
				return true;
			}
			if (text.Contains("environment/map"))
			{
				return true;
			}
			if (text.Contains("systems/levelgeneration/levelgenerationroot"))
			{
				return true;
			}
			if (text.Contains("levelgenerationroot"))
			{
				return true;
			}
			if (text2.Contains("terrain") || text2.Contains("ground") || text2.Contains("floor") || text2.Contains("landscape") || text2.Contains("mapterrain") || text2.Contains("moonterrain") || text2.Contains("outsideground") || text2.Contains("outsidefloor"))
			{
				return true;
			}
			if ((text2.Contains("ladder") || text2.Contains("rock") || text2.Contains("boulder") || text2.Contains("stone") || text2.Contains("hatch") || text2.Contains("entrance") || text2.Contains("fireexit") || text2.Contains("door") || text2.Contains("fence") || text2.Contains("pipe") || text2.Contains("beam") || text2.Contains("cliff")) && (text.Contains("environment") || text.Contains("map") || text.Contains("level") || text.Contains("outside")))
			{
				return true;
			}
			return false;
		}

		private static string GetHierarchyPath(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return "";
			}
			List<string> list = new List<string>();
			Transform val = obj.transform;
			while ((Object)(object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}

		private static bool IsPracticeObject(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			string text = ((Object)obj).name ?? "";
			return text.StartsWith("Practice", StringComparison.OrdinalIgnoreCase);
		}

		internal static string? HandleShipTerminalPracticeCommand(string rawInput)
		{
			if (!PracticeActive)
			{
				return null;
			}
			string text = rawInput.Trim();
			if (string.IsNullOrWhiteSpace(text))
			{
				return null;
			}
			string[] array = text.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
			string text2 = ((array.Length != 0) ? Normalize(array[0]) : "");
			bool flag = text2 == "p" || text2 == "ps" || text2 == "practice";
			string commandText = ((!flag) ? text : ((array.Length >= 2) ? array[1].Trim() : "help"));
			return HandlePracticeCommandBody(commandText, !flag);
		}

		private static string? HandlePracticeCommandBody(string commandText, bool returnNullIfUnknown = false)
		{
			if (string.IsNullOrWhiteSpace(commandText))
			{
				commandText = "help";
			}
			string[] array = commandText.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
			string text = Normalize(array[0]);
			string text2 = ((array.Length >= 2) ? array[1].Trim() : "");
			switch (text)
			{
			case "help":
			case "h":
				return GetPracticeTerminalHelpText();
			case "jp":
			case "ja":
			case "japanese":
			case "en":
			case "eng":
			case "english":
				return "Language switching has been removed. Use help.";
			case "regen":
			case "regenerate":
			case "arena":
				RegenerateArenaFromCommand();
				return "Practice arena regenerated. The Practice NavMesh inside the red enemy area was also rebuilt.";
			case "flip":
			case "front":
			case "direction":
				FlipArenaDirectionFromCommand();
				return "Practice arena direction flipped and regenerated. If the arena is behind the ship, use flip once more.";
			case "data":
			case "dat":
				if (Normalize(text2) == "entity" || Normalize(text2) == "entities" || Normalize(text2) == "enemy" || Normalize(text2) == "enemies")
				{
					return GetEntityDataText();
				}
				if (Normalize(text2) == "item" || Normalize(text2) == "items" || Normalize(text2) == "store" || Normalize(text2) == "stores")
				{
					return GetStoreItemDataText();
				}
				if (Normalize(text2) == "scrap" || Normalize(text2) == "scraps")
				{
					return GetScrapDataText();
				}
				return GetPracticeDataIndexText();
			case "datae":
			case "entitydata":
			case "enemydata":
				return GetEntityDataText();
			case "datai":
			case "itemdata":
			case "storedata":
			case "storeitems":
				return GetStoreItemDataText();
			case "datas":
			case "scrapdata":
			case "scrapsdata":
				return GetScrapDataText();
			case "dumpenemies":
			case "dumpenemy":
				return DumpEnemyTypesToLog();
			case "dumpitems":
			case "dumpitem":
				return DumpItemsToLog();
			case "entity":
			case "enemy":
			case "ent":
				return SpawnEnemyCommand(text2);
			case "delete":
			case "del":
			case "clear":
				if (Normalize(text2) == "item" || Normalize(text2) == "items")
				{
					return DeleteDroppedItemsCommand();
				}
				return DeleteEnemyCommand(string.IsNullOrWhiteSpace(text2) ? "all" : text2);
			case "deli":
			case "delitem":
			case "deleteitem":
			case "clearitem":
			case "clearitems":
				return DeleteDroppedItemsCommand();
			case "store":
			case "sto":
			case "item":
			case "scrap":
				return SpawnPracticeItemCommand(text2);
			case "reset":
			case "recall":
			case "back":
				return ResetAllEnemiesToRespawnPoint();
			case "heal":
			case "recover":
				return FullHealLocalPlayerCommand();
			case "hp":
			case "health":
				if (!string.IsNullOrWhiteSpace(text2))
				{
					return SetLocalPlayerHealthCommand(text2);
				}
				return FullHealLocalPlayerCommand();
			case "sethp":
			case "sethealth":
			case "lowhp":
				return SetLocalPlayerHealthCommand(text2);
			case "dmg":
			case "damage":
			case "hurt":
				return DamageLocalPlayerCommand(text2);
			case "stats":
			case "stat":
				return TogglePracticeStatsOverlayCommand();
			case "hb":
			case "hit":
			case "hitbox":
			case "hitboxes":
				return TogglePracticeHitboxOverlayCommand();
			case "cmdtest":
			case "commandtest":
				return CommandSelfTestCommand();
			case "aidiag":
			case "enemyai":
			case "enemydiag":
				return GetEnemyAiDiagnosticCommand();
			case "god":
			case "godmode":
			case "inv":
			case "invincible":
			case "immortal":
				return ToggleLocalPlayerInvincibleCommand();
			case "fixhands":
			case "freehands":
				return FixHandsCommand();
			case "handstate":
			case "hands":
				return GetHandStateCommand();
			case "invstate":
			case "godstate":
				return GetInvStateCommand();
			case "cage":
				return SetEnemyOnlyCageCommand(text2);
			case "leash":
				return SetEnemyLeashCommand(text2);
			case "rescue":
			case "autorescue":
				return SetAutoRescueCommand(text2);
			case "crit":
			case "critical":
			case "critinjury":
				return SetCriticalInjuryCommand(text2);
			case "critfix":
			case "clearcrit":
			case "criticalfix":
				return ForceCriticalVisualClearCommand();
			case "critfx":
			case "critvisual":
			case "criticalvisual":
				return SetCriticalVisualHealthGateCommand(text2);
			case "manstate":
			case "manediag":
				return GetManeaterStateCommand();
			case "maninspect":
			case "manins":
			case "manmethods":
			case "manfields":
				return GetManeaterInspectCommand((text == "manmethods") ? "methods" : ((text == "manfields") ? "fields" : text2));
			case "manreset":
			case "manfix":
				return ResetManeaterStateCommand();
			case "manfresh":
				return SetManeaterHardRefreshCommand(text2);
			case "manadult":
			case "adultman":
			case "manvisualadult":
				return SetManeaterForceAdultCommand(text2);
			case "manadultrespawn":
			case "manadultrefresh":
			case "adultrespawn":
				return SetManeaterAdultRespawnCommand(text2);
			case "jesfix":
			case "jesterfix":
			case "jesaggro":
			case "jesteraggro":
				return SetJesterPracticeAggroCommand(text2);
			case "jesreset":
			case "jesternoreset":
				return SetJesterPracticeNoResetCommand(text2);
			case "tulphys":
			case "tulipphys":
				return SetTulipPhysicsDiagnosticCommand(text2);
			case "tulguard":
			case "tulipguard":
				return SetTulipBoundaryGuardCommand(text2);
			case "hideout":
			case "stealthout":
			case "outsidehide":
				return SetHideOutsidePlayersCommand(text2);
			case "diag":
				return GetAllDiagnosticStatus();
			case "language":
			case "lang":
			case "lan":
				return "Language switching has been removed. Use help.";
			default:
			{
				string text3 = HandleCompactPracticeCommand(commandText, returnNullIfUnknown: true);
				if (text3 != null)
				{
					return text3;
				}
				if (returnNullIfUnknown)
				{
					return null;
				}
				return "Unknown Practice command: " + commandText + "\n\n" + GetPracticeTerminalHelpText();
			}
			}
		}

		internal static string? HandleCompactPracticeCommand(string rawInput, bool returnNullIfUnknown, bool allowDataCommands = true)
		{
			if (!PracticeActive)
			{
				return returnNullIfUnknown ? null : "Practice mode is not active.";
			}
			string text = rawInput.Trim();
			if (string.IsNullOrWhiteSpace(text))
			{
				return returnNullIfUnknown ? null : "Empty command.";
			}
			string text2 = Normalize(text);
			string[] array = text.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
			string text3 = ((array.Length != 0) ? Normalize(array[0]) : "");
			string text4 = ((array.Length >= 2) ? array[1].Trim() : "");
			if (!string.IsNullOrWhiteSpace(text4))
			{
				switch (text3)
				{
				case "hp":
				case "health":
				case "sethp":
				case "sethealth":
				case "lowhp":
					return SetLocalPlayerHealthCommand(text4);
				case "dmg":
				case "damage":
				case "hurt":
					return DamageLocalPlayerCommand(text4);
				case "entity":
				case "enemy":
				case "ent":
					return SpawnEnemyCommand(text4);
				case "store":
				case "sto":
				case "item":
				case "scrap":
					return SpawnPracticeItemCommand(text4);
				case "delete":
				case "del":
				case "clear":
					return DeleteEnemyCommand(text4);
				case "cage":
				case "leash":
				case "rescue":
				case "autorescue":
				case "crit":
				case "critical":
				case "critinjury":
				case "critfx":
				case "critvisual":
				case "criticalvisual":
				case "maninspect":
				case "manins":
				case "manmethods":
				case "manfields":
				case "manfresh":
				case "manadult":
				case "adultman":
				case "manvisualadult":
				case "manadultrespawn":
				case "manadultrefresh":
				case "adultrespawn":
				case "jesfix":
				case "jesterfix":
				case "jesaggro":
				case "jesteraggro":
				case "tulphys":
				case "tulipphys":
				case "tulguard":
				case "tulipguard":
				case "hideout":
				case "stealthout":
				case "outsidehide":
					return HandlePracticeCommandBody(text);
				}
			}
			if (text3 == "aidig" || text3 == "aisig")
			{
				return GetEnemyAiDiagnosticCommand();
			}
			if (allowDataCommands)
			{
				if (text2 == "help" || text2 == "h")
				{
					return GetPracticeTerminalHelpText();
				}
				if (text2 == "data" || text2 == "dat")
				{
					return GetPracticeDataIndexText();
				}
				if (text2 == "datae" || text2 == "entitydata" || text2 == "enemydata")
				{
					return GetEntityDataText();
				}
				switch (text2)
				{
				default:
					if (!(text2 == "stores"))
					{
						break;
					}
					goto case "datai";
				case "datai":
				case "itemdata":
				case "items":
				case "store":
					return GetStoreItemDataText();
				}
				switch (text2)
				{
				default:
					if (!(text2 == "scraps"))
					{
						break;
					}
					goto case "datas";
				case "datas":
				case "scrapdata":
				case "scrap":
					return GetScrapDataText();
				}
				if (text2 == "dumpenemies" || text2 == "dumpenemy")
				{
					return DumpEnemyTypesToLog();
				}
				if (text2 == "dumpitems" || text2 == "dumpitem")
				{
					return DumpItemsToLog();
				}
			}
			if (text2 == "regen" || text2 == "regenerate" || text2 == "arena")
			{
				RegenerateArenaFromCommand();
				return "Practice arena regenerated.";
			}
			if (text2 == "flip" || text2 == "front" || text2 == "direction")
			{
				FlipArenaDirectionFromCommand();
				return "Practice arena direction flipped and regenerated.";
			}
			switch (text2)
			{
			default:
				if (!(text2 == "delall"))
				{
					switch (text2)
					{
					default:
						if (!(text2 == "clearitems"))
						{
							if (text2 == "reset" || text2 == "recall" || text2 == "back")
							{
								return ResetAllEnemiesToRespawnPoint();
							}
							if (text2 == "heal" || text2 == "recover")
							{
								return FullHealLocalPlayerCommand();
							}
							if (text2 == "hp" || text2 == "health")
							{
								return FullHealLocalPlayerCommand();
							}
							if (!text2.StartsWith("sethp ", StringComparison.Ordinal) && !text2.StartsWith("sethealth ", StringComparison.Ordinal) && !text2.StartsWith("lowhp ", StringComparison.Ordinal) && !text2.StartsWith("hp ", StringComparison.Ordinal) && !text2.StartsWith("health ", StringComparison.Ordinal))
							{
								if (text2.StartsWith("dmg ", StringComparison.Ordinal) || text2.StartsWith("damage ", StringComparison.Ordinal) || text2.StartsWith("hurt ", StringComparison.Ordinal))
								{
									string argument = (text2.StartsWith("damage ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 7)).Trim() : text.Substring(Math.Min(text.Length, text2.StartsWith("hurt ", StringComparison.Ordinal) ? 5 : 4)).Trim());
									return DamageLocalPlayerCommand(argument);
								}
								if (text2 == "stats" || text2 == "stat")
								{
									return TogglePracticeStatsOverlayCommand();
								}
								switch (text2)
								{
								default:
									if (!(text2 == "hitboxes"))
									{
										if (text2 == "cmdtest" || text2 == "commandtest")
										{
											return CommandSelfTestCommand();
										}
										if (text2 == "aidiag" || text2 == "enemyai" || text2 == "enemydiag")
										{
											return GetEnemyAiDiagnosticCommand();
										}
										switch (text2)
										{
										default:
											if (!(text2 == "immortal"))
											{
												if (text2 == "fixhands" || text2 == "freehands")
												{
													return FixHandsCommand();
												}
												if (text2 == "handstate" || text2 == "hands")
												{
													return GetHandStateCommand();
												}
												if (text2 == "invstate" || text2 == "godstate")
												{
													return GetInvStateCommand();
												}
												if (text2 == "manstate" || text2 == "manediag")
												{
													return GetManeaterStateCommand();
												}
												switch (text2)
												{
												default:
													if (!(text2 == "manfields"))
													{
														if (text2 == "manfresh" || text2.StartsWith("manfresh ", StringComparison.Ordinal))
														{
															string maneaterHardRefreshCommand = ((text2 == "manfresh") ? "" : text.Substring(Math.Min(text.Length, 8)).Trim());
															return SetManeaterHardRefreshCommand(maneaterHardRefreshCommand);
														}
														if (text2 == "manadult" || text2.StartsWith("manadult ", StringComparison.Ordinal) || text2 == "adultman" || text2.StartsWith("adultman ", StringComparison.Ordinal) || text2 == "manvisualadult" || text2.StartsWith("manvisualadult ", StringComparison.Ordinal))
														{
															int num = (text2.StartsWith("manvisualadult", StringComparison.Ordinal) ? 14 : (text2.StartsWith("adultman", StringComparison.Ordinal) ? 8 : 8));
															string maneaterForceAdultCommand = ((text.Length > num) ? text.Substring(num).Trim() : "");
															return SetManeaterForceAdultCommand(maneaterForceAdultCommand);
														}
														if (text2 == "manadultrespawn" || text2.StartsWith("manadultrespawn ", StringComparison.Ordinal) || text2 == "manadultrefresh" || text2.StartsWith("manadultrefresh ", StringComparison.Ordinal) || text2 == "adultrespawn" || text2.StartsWith("adultrespawn ", StringComparison.Ordinal))
														{
															int num2 = (text2.StartsWith("manadultrefresh", StringComparison.Ordinal) ? 15 : (text2.StartsWith("adultrespawn", StringComparison.Ordinal) ? 12 : 15));
															string maneaterAdultRespawnCommand = ((text.Length > num2) ? text.Substring(num2).Trim() : "");
															return SetManeaterAdultRespawnCommand(maneaterAdultRespawnCommand);
														}
														if (text2 == "crit" || text2.StartsWith("crit ", StringComparison.Ordinal) || text2 == "critical" || text2.StartsWith("critical ", StringComparison.Ordinal) || text2 == "critinjury" || text2.StartsWith("critinjury ", StringComparison.Ordinal))
														{
															int num3 = (text2.StartsWith("critinjury", StringComparison.Ordinal) ? 10 : (text2.StartsWith("critical", StringComparison.Ordinal) ? 8 : 4));
															string criticalInjuryCommand = ((text.Length > num3) ? text.Substring(num3).Trim() : "");
															return SetCriticalInjuryCommand(criticalInjuryCommand);
														}
														if (text2 == "critfix" || text2 == "clearcrit" || text2 == "criticalfix")
														{
															return ForceCriticalVisualClearCommand();
														}
														if (text2 == "jesfix" || text2.StartsWith("jesfix ", StringComparison.Ordinal) || text2 == "jesterfix" || text2.StartsWith("jesterfix ", StringComparison.Ordinal) || text2 == "jesaggro" || text2.StartsWith("jesaggro ", StringComparison.Ordinal) || text2 == "jesteraggro" || text2.StartsWith("jesteraggro ", StringComparison.Ordinal))
														{
															int num4 = (text2.StartsWith("jesteraggro", StringComparison.Ordinal) ? 11 : (text2.StartsWith("jesterfix", StringComparison.Ordinal) ? 9 : (text2.StartsWith("jesaggro", StringComparison.Ordinal) ? 8 : 6)));
															string jesterPracticeAggroCommand = ((text.Length > num4) ? text.Substring(num4).Trim() : "");
															return SetJesterPracticeAggroCommand(jesterPracticeAggroCommand);
														}
														if (text2 == "jesreset" || text2.StartsWith("jesreset ", StringComparison.Ordinal) || text2 == "jesternoreset" || text2.StartsWith("jesternoreset ", StringComparison.Ordinal))
														{
															int num5 = (text2.StartsWith("jesternoreset", StringComparison.Ordinal) ? 14 : 8);
															string jesterPracticeNoResetCommand = ((text.Length > num5) ? text.Substring(num5).Trim() : "");
															return SetJesterPracticeNoResetCommand(jesterPracticeNoResetCommand);
														}
														if (text2 == "critfx" || text2.StartsWith("critfx ", StringComparison.Ordinal) || text2 == "critvisual" || text2.StartsWith("critvisual ", StringComparison.Ordinal) || text2 == "criticalvisual" || text2.StartsWith("criticalvisual ", StringComparison.Ordinal))
														{
															int num6 = (text2.StartsWith("criticalvisual", StringComparison.Ordinal) ? 14 : (text2.StartsWith("critvisual", StringComparison.Ordinal) ? 10 : 6));
															string criticalVisualHealthGateCommand = ((text.Length > num6) ? text.Substring(num6).Trim() : "");
															return SetCriticalVisualHealthGateCommand(criticalVisualHealthGateCommand);
														}
														if (text2.StartsWith("maninspect", StringComparison.Ordinal) || text2.StartsWith("manins", StringComparison.Ordinal))
														{
															string argument2 = (text2.StartsWith("maninspect", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 6)).Trim());
															return GetManeaterInspectCommand(argument2);
														}
														if (text2 == "diag")
														{
															return GetAllDiagnosticStatus();
														}
														if (text2.StartsWith("cage", StringComparison.Ordinal))
														{
															string enemyOnlyCageCommand = ((text.Length > 4) ? text.Substring(4).Trim() : "");
															return SetEnemyOnlyCageCommand(enemyOnlyCageCommand);
														}
														if (text2.StartsWith("leash", StringComparison.Ordinal))
														{
															string enemyLeashCommand = ((text.Length > 5) ? text.Substring(5).Trim() : "");
															return SetEnemyLeashCommand(enemyLeashCommand);
														}
														if (text2.StartsWith("rescue", StringComparison.Ordinal) || text2.StartsWith("autorescue", StringComparison.Ordinal))
														{
															string autoRescueCommand = (text2.StartsWith("autorescue", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 6)).Trim());
															return SetAutoRescueCommand(autoRescueCommand);
														}
														if (text2.StartsWith("tulphys", StringComparison.Ordinal) || text2.StartsWith("tulipphys", StringComparison.Ordinal))
														{
															string tulipPhysicsDiagnosticCommand = (text2.StartsWith("tulipphys", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 8)).Trim() : text.Substring(Math.Min(text.Length, 7)).Trim());
															return SetTulipPhysicsDiagnosticCommand(tulipPhysicsDiagnosticCommand);
														}
														if (text2.StartsWith("tulguard", StringComparison.Ordinal) || text2.StartsWith("tulipguard", StringComparison.Ordinal))
														{
															string tulipBoundaryGuardCommand = (text2.StartsWith("tulipguard", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 8)).Trim());
															return SetTulipBoundaryGuardCommand(tulipBoundaryGuardCommand);
														}
														if (text2 == "diaglog" || text2 == "diagpath")
														{
															return "Diagnostic log: " + PracticeDiagnosticFile.LogPath;
														}
														if (text2.StartsWith("hideout", StringComparison.Ordinal) || text2.StartsWith("stealthout", StringComparison.Ordinal) || text2.StartsWith("outsidehide", StringComparison.Ordinal))
														{
															string hideOutsidePlayersCommand = (text2.StartsWith("outsidehide", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 11)).Trim() : text.Substring(Math.Min(text.Length, text2.StartsWith("stealthout", StringComparison.Ordinal) ? 9 : 7)).Trim());
															return SetHideOutsidePlayersCommand(hideOutsidePlayersCommand);
														}
														if (array.Length == 1 && (text2 == "jes2" || text2 == "jester2"))
														{
															return "jes2 has been removed. Use jes.";
														}
														ParsedCommand parsedCommand = ParseCompactNameAndCount(text);
														if (string.IsNullOrWhiteSpace(parsedCommand.Name))
														{
															return returnNullIfUnknown ? null : ("Unknown command: " + rawInput);
														}
														TryResolveEnemyTypes();
														EnemyDefinition enemyDefinition = FindEnemyDefinition(parsedCommand.Name);
														if (enemyDefinition != null)
														{
															return SpawnEnemyCommand($"{enemyDefinition.PrimaryAlias} {parsedCommand.Count}");
														}
														string text5 = SpawnPracticeItemCommand($"{parsedCommand.Name} {parsedCommand.Count}");
														if (!text5.StartsWith("Unknown item", StringComparison.OrdinalIgnoreCase))
														{
															return text5;
														}
														return returnNullIfUnknown ? null : ("Unknown command: " + rawInput);
													}
													goto case "maninspect";
												case "maninspect":
												case "manins":
												case "manmethods":
												{
													string argument3 = ((text2 == "manmethods") ? "methods" : ((text2 == "manfields") ? "fields" : ""));
													return GetManeaterInspectCommand(argument3);
												}
												}
											}
											goto case "god";
										case "god":
										case "godmode":
										case "inv":
										case "invincible":
											return ToggleLocalPlayerInvincibleCommand();
										}
									}
									goto case "hb";
								case "hb":
								case "hit":
								case "hitbox":
									return TogglePracticeHitboxOverlayCommand();
								}
							}
							string localPlayerHealthCommand = (text2.StartsWith("sethealth ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : (text2.StartsWith("sethp ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 6)).Trim() : (text2.StartsWith("lowhp ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 6)).Trim() : ((!text2.StartsWith("health ", StringComparison.Ordinal)) ? text.Substring(Math.Min(text.Length, 3)).Trim() : text.Substring(Math.Min(text.Length, 7)).Trim()))));
							return SetLocalPlayerHealthCommand(localPlayerHealthCommand);
						}
						goto case "deli";
					case "deli":
					case "deleteitem":
					case "deleteitems":
					case "delitem":
					case "clearitem":
						return DeleteDroppedItemsCommand();
					}
				}
				goto case "delete";
			case "delete":
			case "del":
			case "clear":
			case "deleteall":
				return DeleteAllEnemiesAndCorpses();
			}
		}

		private static string GetPracticeTerminalHelpText()
		{
			return "PRACTICE SANDBOX COMMANDS\n\nDuring Practice, enter commands either in the normal in-game chat (/ to open it) or in the ship Terminal.\nThe same commands work in both places without a p prefix.\n\nENEMIES\nmas      = spawn 1 masked\nmas3     = spawn 3 masked\nthu      = spawn 1 thumper\ndog      = spawn 1 eyeless dog\nold      = spawn 1 Old Bird\njes      = spawn Jester and progress normal box -> crank -> pop -> chase\ndata     = show data categories\ndatae    = show entity spawn commands / aliases, including special and internal entities\n\nITEMS\nsho      = spawn 1 shovel\nshot     = spawn 1 shotgun\ngbar     = spawn 1 gold bar\ndatai    = show store / purchasable item aliases\ndatas    = show scrap + special / system item aliases\n\nPLAYER\nheal     = fully heal and clear Critical Injury effects\nsethp 10 / hp 10 = set HP to 10\ndmg 40 / hurt 40 = subtract 40 HP\nstats    = toggle HP/ST/HB/INV display (default ON)\nhb / hit = toggle hitbox visualization (default OFF)\ngod      = toggle invincible mode\n\nREMOVE / RESET\ndeli     = dele