Decompiled source of RealPortal v1.0.6

plugins/RealPortal.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using AmplifyOcclusion;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using RealPortal.Api;
using RealPortal.Engine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.PostProcessing;
using UnityEngine.Rendering;
using UnityStandardAssets.ImageEffects;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("RealPortalLab")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("RealPortal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RealPortal")]
[assembly: AssemblyTitle("RealPortal")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RealPortal
{
	internal static class AreaRenderState
	{
		internal struct Values
		{
			public Quaternion LightRot;

			public float LightIntensity;

			public Color LightColor;

			public Color FogColor;

			public float FogDensity;

			public Color Ambient;

			public float CloudRain;

			public float CloudOpacity;

			public Vector4 SkyDir;

			public Vector4 SunDir;

			public Color SunFog;

			public Color SunCol;

			public Color AmbientGlobal;

			public float Wet;

			public float Aurora;

			public Vector4 Wind1;

			public Vector4 Wind2;

			public Vector4 WindForce;
		}

		private sealed class Snapshot
		{
			public EnvSetup Env;

			public float Wet;

			public Values V;
		}

		private static readonly int s_skyboxSunDir = Shader.PropertyToID("_SkyboxSunDir");

		private static readonly int s_sunDir = Shader.PropertyToID("_SunDir");

		private static readonly int s_sunFogColor = Shader.PropertyToID("_SunFogColor");

		private static readonly int s_sunColor = Shader.PropertyToID("_SunColor");

		private static readonly int s_ambientColor = Shader.PropertyToID("_AmbientColor");

		private static readonly int s_wet = Shader.PropertyToID("_Wet");

		private static readonly int s_aurora = Shader.PropertyToID("_AuroraStrength");

		private static readonly int s_rain = Shader.PropertyToID("_Rain");

		private static readonly int s_opacity = Shader.PropertyToID("_Opacity");

		private static readonly int s_wind1 = Shader.PropertyToID("_GlobalWind1");

		private static readonly int s_wind2 = Shader.PropertyToID("_GlobalWind2");

		private static readonly int s_windForce = Shader.PropertyToID("_GlobalWindForce");

		private static Values s_game;

		private static Values s_cur;

		private static Material s_clouds;

		private static bool s_open;

		private static int s_batch;

		internal static int LabWrites;

		internal static int LabSkipped;

		private static readonly List<Snapshot> s_snapshots = new List<Snapshot>();

		private static int s_count;

		private static int s_snapshotBatch = -1;

		internal static bool Open => s_open;

		internal static ref readonly Values Game => ref s_game;

		internal static void Begin(EnvMan em)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			Light dirLight = em.m_dirLight;
			s_game.LightRot = ((Component)dirLight).transform.rotation;
			s_game.LightIntensity = dirLight.intensity;
			s_game.LightColor = dirLight.color;
			s_game.FogColor = RenderSettings.fogColor;
			s_game.FogDensity = RenderSettings.fogDensity;
			s_game.Ambient = RenderSettings.ambientLight;
			s_clouds = (((Object)(object)em.m_clouds != (Object)null) ? ((Renderer)em.m_clouds).sharedMaterial : null);
			if ((Object)(object)s_clouds != (Object)null)
			{
				s_game.CloudRain = s_clouds.GetFloat(s_rain);
				s_game.CloudOpacity = s_clouds.GetFloat(s_opacity);
			}
			s_game.SkyDir = Shader.GetGlobalVector(s_skyboxSunDir);
			s_game.SunDir = Shader.GetGlobalVector(s_sunDir);
			s_game.SunFog = Shader.GetGlobalColor(s_sunFogColor);
			s_game.SunCol = Shader.GetGlobalColor(s_sunColor);
			s_game.AmbientGlobal = Shader.GetGlobalColor(s_ambientColor);
			s_game.Wet = Shader.GetGlobalFloat(s_wet);
			s_game.Aurora = Shader.GetGlobalFloat(s_aurora);
			s_game.Wind1 = Shader.GetGlobalVector(s_wind1);
			s_game.Wind2 = Shader.GetGlobalVector(s_wind2);
			s_game.WindForce = Shader.GetGlobalVector(s_windForce);
			s_cur = s_game;
			s_open = true;
			s_batch++;
		}

		internal static void Apply(EnvMan em, in Values to)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			if (!s_open)
			{
				return;
			}
			int num = 0;
			Light val = (((Object)(object)em != (Object)null) ? em.m_dirLight : null);
			if ((Object)(object)val != (Object)null)
			{
				if (!Eq(s_cur.LightRot, to.LightRot))
				{
					((Component)val).transform.rotation = to.LightRot;
					num++;
				}
				if (s_cur.LightIntensity != to.LightIntensity)
				{
					val.intensity = to.LightIntensity;
					num++;
				}
				if (!Eq(s_cur.LightColor, to.LightColor))
				{
					val.color = to.LightColor;
					num++;
				}
			}
			if (!Eq(s_cur.FogColor, to.FogColor))
			{
				RenderSettings.fogColor = to.FogColor;
				num++;
			}
			if (s_cur.FogDensity != to.FogDensity)
			{
				RenderSettings.fogDensity = to.FogDensity;
				num++;
			}
			if (!Eq(s_cur.Ambient, to.Ambient))
			{
				RenderSettings.ambientLight = to.Ambient;
				num++;
			}
			if ((Object)(object)s_clouds != (Object)null)
			{
				if (s_cur.CloudRain != to.CloudRain)
				{
					s_clouds.SetFloat(s_rain, to.CloudRain);
					num++;
				}
				if (s_cur.CloudOpacity != to.CloudOpacity)
				{
					s_clouds.SetFloat(s_opacity, to.CloudOpacity);
					num++;
				}
			}
			if (!Eq(s_cur.SkyDir, to.SkyDir))
			{
				Shader.SetGlobalVector(s_skyboxSunDir, to.SkyDir);
				num++;
			}
			if (!Eq(s_cur.SunDir, to.SunDir))
			{
				Shader.SetGlobalVector(s_sunDir, to.SunDir);
				num++;
			}
			if (!Eq(s_cur.SunFog, to.SunFog))
			{
				Shader.SetGlobalColor(s_sunFogColor, to.SunFog);
				num++;
			}
			if (!Eq(s_cur.SunCol, to.SunCol))
			{
				Shader.SetGlobalColor(s_sunColor, to.SunCol);
				num++;
			}
			if (!Eq(s_cur.AmbientGlobal, to.AmbientGlobal))
			{
				Shader.SetGlobalColor(s_ambientColor, to.AmbientGlobal);
				num++;
			}
			if (s_cur.Wet != to.Wet)
			{
				Shader.SetGlobalFloat(s_wet, to.Wet);
				num++;
			}
			if (s_cur.Aurora != to.Aurora)
			{
				Shader.SetGlobalFloat(s_aurora, to.Aurora);
				num++;
			}
			if (!Eq(s_cur.Wind1, to.Wind1))
			{
				Shader.SetGlobalVector(s_wind1, to.Wind1);
				num++;
			}
			if (!Eq(s_cur.Wind2, to.Wind2))
			{
				Shader.SetGlobalVector(s_wind2, to.Wind2);
				num++;
			}
			if (!Eq(s_cur.WindForce, to.WindForce))
			{
				Shader.SetGlobalVector(s_windForce, to.WindForce);
				num++;
			}
			s_cur = to;
			LabWrites += num;
			if (num == 0)
			{
				LabSkipped++;
			}
		}

		internal static void ToGame(EnvMan em)
		{
			if (s_open)
			{
				Apply(em, in s_game);
			}
		}

		internal static void End(EnvMan em)
		{
			if (s_open)
			{
				if ((Object)(object)em != (Object)null)
				{
					Apply(em, in s_game);
				}
				s_open = false;
				s_clouds = null;
			}
		}

		internal static bool Find(EnvSetup env, float wet, out Values v)
		{
			if (s_snapshotBatch == s_batch)
			{
				for (int i = 0; i < s_count; i++)
				{
					Snapshot snapshot = s_snapshots[i];
					if (snapshot.Env == env && snapshot.Wet == wet)
					{
						v = snapshot.V;
						return true;
					}
				}
			}
			v = default(Values);
			return false;
		}

		internal static void Keep(EnvSetup env, float wet, in Values v)
		{
			if (s_snapshotBatch != s_batch)
			{
				s_snapshotBatch = s_batch;
				s_count = 0;
			}
			if (s_count == s_snapshots.Count)
			{
				s_snapshots.Add(new Snapshot());
			}
			Snapshot snapshot = s_snapshots[s_count++];
			snapshot.Env = env;
			snapshot.Wet = wet;
			snapshot.V = v;
		}

		private static bool Eq(Quaternion a, Quaternion b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (a.x == b.x && a.y == b.y && a.z == b.z)
			{
				return a.w == b.w;
			}
			return false;
		}

		private static bool Eq(Color a, Color b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (a.r == b.r && a.g == b.g && a.b == b.b)
			{
				return a.a == b.a;
			}
			return false;
		}

		private static bool Eq(Vector4 a, Vector4 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (a.x == b.x && a.y == b.y && a.z == b.z)
			{
				return a.w == b.w;
			}
			return false;
		}

		internal static void Clear()
		{
			s_snapshots.Clear();
			s_count = 0;
			s_snapshotBatch = -1;
		}
	}
	internal static class BaseView
	{
		private sealed class Zone
		{
			public Vector2s Id;

			public int Index;

			public int Mark;

			public float MinY;

			public float MaxY;

			public bool HasGround;

			public readonly List<Renderer> Ground = new List<Renderer>();

			public List<Item> Items = new List<Item>();

			public List<Item> Next = new List<Item>();

			public readonly List<ZDO> Snapshot = new List<ZDO>();

			public int Cursor = -1;

			public int ListedVersion = int.MinValue;

			public float ListedAt = float.NegativeInfinity;

			public bool Near;

			public bool Ring;

			public bool InView;

			public bool Close;

			public float Distance;

			public void Reset(Vector2s id, int index)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				Id = id;
				Index = index;
				HasGround = false;
				Cursor = -1;
				ListedVersion = int.MinValue;
				ListedAt = float.NegativeInfinity;
			}

			public void Clear()
			{
				Ground.Clear();
				Items.Clear();
				Next.Clear();
				Snapshot.Clear();
				Cursor = -1;
			}
		}

		private struct Item
		{
			public Parts Parts;

			public bool Distant;
		}

		private sealed class Parts
		{
			public ZNetView View;

			public Transform Root;

			public Renderer[] Renderers;

			public sbyte[] Level;

			public short[] Group;

			public Vector3[] GroupAt;

			public float[] GroupSize;

			public float[][] Heights;

			public bool Mover;

			public float ListedAt;
		}

		private struct Lively
		{
			public ParticleSystemRenderer[] Renderers;

			public Transform Root;

			public int Index;

			public bool Distant;
		}

		private struct LightEntry
		{
			public Light Light;

			public int Index;

			public bool Distant;
		}

		internal static int LabBaseHidden;

		internal static int LabZones;

		internal static int LabZonesInView;

		internal static long LabListed;

		private const int ZoneSpan = 512;

		private const float ZoneMargin = 16f;

		private const float AboveGround = 96f;

		private const float BelowGround = 32f;

		private const int ListAtLeast = 8;

		private const int ClutterPerFrame = 256;

		private const double ListBudgetMs = 0.25;

		private const float ZoneRelist = 2f;

		private const float ViewRelist = 10f;

		private const float LodMargin = 0.75f;

		private const int Culled = -100;

		internal static readonly HashSet<Transform> Crossing = new HashSet<Transform>();

		private static int[] s_zoneOf;

		private static readonly List<Zone> s_zones = new List<Zone>();

		private static readonly Stack<Zone> s_pool = new Stack<Zone>();

		private static readonly HashSet<Vector2s> s_set = new HashSet<Vector2s>();

		private static int s_mark;

		private static int s_version = int.MinValue;

		private static int s_near = -1;

		private static int s_total = -1;

		private static bool s_classic;

		private static Vector2s s_me;

		private static float s_zonesAt;

		private static float s_listsAt;

		private static float s_sweepAt;

		private static float s_errorAt;

		private static readonly List<LightEntry> s_lights = new List<LightEntry>();

		private static readonly List<Lively> s_lively = new List<Lively>();

		private static List<Renderer> s_clutter = new List<Renderer>();

		private static List<Renderer> s_clutterNext = new List<Renderer>();

		private static int s_clutterCursor;

		private static Vector3 s_clutterFrom;

		private static bool s_clutterHas;

		private static readonly Dictionary<ZNetView, Parts> s_parts = new Dictionary<ZNetView, Parts>();

		private static readonly Dictionary<ZNetView, ParticleSystemRenderer[]> s_particlesOf = new Dictionary<ZNetView, ParticleSystemRenderer[]>();

		private static readonly Dictionary<LightLod, bool> s_lightDistant = new Dictionary<LightLod, bool>();

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

		private static readonly List<Light> s_off = new List<Light>();

		private static readonly Plane[] s_planes = (Plane[])(object)new Plane[6];

		private static int[] s_level = new int[16];

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

		private static readonly List<LODGroup> s_groups = new List<LODGroup>();

		private static readonly List<ParticleSystemRenderer> s_particles = new List<ParticleSystemRenderer>();

		private static readonly List<ZNetView> s_views = new List<ZNetView>();

		private static readonly List<Vector3> s_points = new List<Vector3>();

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

		private static readonly List<ZNetView> s_gone = new List<ZNetView>();

		private static readonly ParticleSystemRenderer[] s_noParticles = (ParticleSystemRenderer[])(object)new ParticleSystemRenderer[0];

		private static readonly Stopwatch s_watch = new Stopwatch();

		private static readonly FieldRef<ZDOMan, List<ZDO>[]> s_objectsBySector = AccessTools.FieldRefAccess<ZDOMan, List<ZDO>[]>("m_objectsBySector");

		private static readonly FieldRef<Heightmap, MeshRenderer> s_heightmapRenderer = AccessTools.FieldRefAccess<Heightmap, MeshRenderer>("m_meshRenderer");

		private static readonly FieldRef<HashSet<LightLod>> s_lodLights = AccessTools.StaticFieldRefAccess<HashSet<LightLod>>(AccessTools.Field(typeof(LightLod), "m_lights"));

		private static readonly FieldRef<LightLod, Light> s_lodLight = AccessTools.FieldRefAccess<LightLod, Light>("m_light");

		private static readonly FieldRef<ClutterSystem, GameObject> s_grassRoot = AccessTools.FieldRefAccess<ClutterSystem, GameObject>("m_grassRoot");

		private static readonly FieldRef<SmokeRenderer, Dictionary<Vector3Int, List<Smoke>>> s_smokeChunks = AccessTools.FieldRefAccess<SmokeRenderer, Dictionary<Vector3Int, List<Smoke>>>("m_chunkedSmoke");

		private static readonly FieldRef<SmokeRenderer, Dictionary<Vector3Int, ParticleSystem>> s_smokeSystems = AccessTools.FieldRefAccess<SmokeRenderer, Dictionary<Vector3Int, ParticleSystem>>("m_chunkedParticleSystems");

		internal static void Hide(PortalSystem sys, Camera cam, bool through)
		{
			if (s_hidden.Count > 0 || s_off.Count > 0)
			{
				Show();
			}
			LabBaseHidden = 0;
			if (!WindowFlags.BaseHidesFar || (Object)(object)sys == (Object)null || (Object)(object)cam == (Object)null || Plugin.Enabled == null || !Plugin.Enabled.Value || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || GameCamera.InFreeFly() || (sys.Areas.Count == 0 && s_zones.Count == 0))
			{
				if (s_zones.Count > 0 || s_clutter.Count > 0)
				{
					Forget();
				}
			}
			else
			{
				if (through)
				{
					return;
				}
				try
				{
					RemoteAreas areas = sys.Areas;
					float unscaledTime = Time.unscaledTime;
					Zones(areas, unscaledTime);
					if (unscaledTime >= s_listsAt)
					{
						s_listsAt = unscaledTime + 1f;
						ListGround();
						ListLights();
						ListLively(areas);
					}
					ListClutter();
					if (unscaledTime >= s_sweepAt)
					{
						s_sweepAt = unscaledTime + 10f;
						Sweep();
					}
					View(cam);
					ListObjects(areas.AreasVersion, unscaledTime);
					Apply(cam);
					LabBaseHidden = s_hidden.Count + s_off.Count;
				}
				catch (Exception ex)
				{
					Show();
					if (Time.unscaledTime >= s_errorAt)
					{
						s_errorAt = Time.unscaledTime + 10f;
						Plugin.Log.LogWarning((object)("Win.BaseHidesFar: hiding the far areas from the game camera failed: " + ex));
					}
				}
			}
		}

		internal static void Show()
		{
			for (int i = 0; i < s_hidden.Count; i++)
			{
				Renderer val = s_hidden[i];
				if ((Object)(object)val != (Object)null)
				{
					val.forceRenderingOff = false;
				}
			}
			s_hidden.Clear();
			for (int j = 0; j < s_off.Count; j++)
			{
				Light val2 = s_off[j];
				if ((Object)(object)val2 != (Object)null)
				{
					((Behaviour)val2).enabled = true;
				}
			}
			s_off.Clear();
		}

		internal static void Clear()
		{
			Forget();
			s_parts.Clear();
			s_particlesOf.Clear();
			s_lightDistant.Clear();
		}

		private static void Forget()
		{
			Show();
			for (int num = s_zones.Count - 1; num >= 0; num--)
			{
				Drop(num);
			}
			s_lights.Clear();
			s_lively.Clear();
			s_clutter.Clear();
			s_clutterNext.Clear();
			s_clutterCursor = 0;
			s_clutterHas = false;
			s_version = int.MinValue;
			s_listsAt = 0f;
			LabZones = (LabZonesInView = 0);
		}

		private static int Index(int x, int y)
		{
			uint num = (uint)(x + 256);
			uint num2 = (uint)(y + 256);
			if (num >= 512 || num2 >= 512)
			{
				return -1;
			}
			return (int)(num2 * 512 + num);
		}

		private static Zone ZoneAt(int index)
		{
			int num = ((index >= 0 && s_zoneOf != null) ? (s_zoneOf[index] - 1) : (-1));
			if (num < 0)
			{
				return null;
			}
			return s_zones[num];
		}

		private static Zone ZoneAt(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Vector2s zone = ZoneSystem.GetZone(point);
			return ZoneAt(Index(zone.x, zone.y));
		}

		private static void Zones(RemoteAreas areas, float now)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			ZNet instance = ZNet.instance;
			Vector2s zone = ZoneSystem.GetZone(instance.GetReferencePosition());
			SimulationDistance syncedSimulationDistance = instance.GetSyncedSimulationDistance();
			bool flag = areas.AreasVersion != s_version || zone != s_me || ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance != s_near || ((SimulationDistance)(ref syncedSimulationDistance)).TotalSimulationDistance != s_total || ((SimulationDistance)(ref syncedSimulationDistance)).IsClassic != s_classic;
			if (!flag && now < s_zonesAt)
			{
				return;
			}
			s_zonesAt = now + 1f;
			if (flag)
			{
				s_listsAt = 0f;
			}
			s_version = areas.AreasVersion;
			s_me = zone;
			s_near = ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance;
			s_total = ((SimulationDistance)(ref syncedSimulationDistance)).TotalSimulationDistance;
			s_classic = ((SimulationDistance)(ref syncedSimulationDistance)).IsClassic;
			s_set.Clear();
			for (int i = 0; i < areas.Count; i++)
			{
				List<Vector2s> list = areas.AreaZones(i);
				for (int j = 0; j < list.Count; j++)
				{
					if (!NearHas(list[j]))
					{
						s_set.Add(list[j]);
					}
				}
			}
			if (s_zoneOf == null)
			{
				s_zoneOf = new int[262144];
			}
			s_mark++;
			foreach (Vector2s item in s_set)
			{
				int num = Index(item.x, item.y);
				if (num >= 0)
				{
					Zone zone2 = ZoneAt(num);
					if (zone2 == null)
					{
						zone2 = ((s_pool.Count > 0) ? s_pool.Pop() : new Zone());
						zone2.Reset(item, num);
						s_zones.Add(zone2);
						s_zoneOf[num] = s_zones.Count;
					}
					zone2.Mark = s_mark;
					zone2.Near = NearHas(item);
					zone2.Ring = RingHas(item);
				}
			}
			s_set.Clear();
			ZoneSystem instance2 = ZoneSystem.instance;
			for (int num2 = s_zones.Count - 1; num2 >= 0; num2--)
			{
				Zone zone3 = s_zones[num2];
				if (zone3.Mark != s_mark)
				{
					if (instance2.IsZoneLoaded(zone3.Id) && !NearHas(zone3.Id))
					{
						zone3.Mark = s_mark;
						zone3.Near = false;
						zone3.Ring = RingHas(zone3.Id);
					}
					else
					{
						Drop(num2);
					}
				}
			}
			LabZones = s_zones.Count;
		}

		private static void Drop(int i)
		{
			Zone zone = s_zones[i];
			s_zoneOf[zone.Index] = 0;
			int num = s_zones.Count - 1;
			if (i != num)
			{
				Zone zone2 = s_zones[num];
				s_zones[i] = zone2;
				s_zoneOf[zone2.Index] = i + 1;
			}
			s_zones.RemoveAt(num);
			zone.Clear();
			s_pool.Push(zone);
		}

		private static bool NearHas(Vector2s z)
		{
			//IL_0000: 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_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)
			int num = Mathf.Max(Mathf.Abs(z.x - s_me.x), Mathf.Abs(z.y - s_me.y));
			if (num <= s_near)
			{
				if (!s_classic && num != 0)
				{
					return ZoneSystem.instance.ZonesWithinRadius(s_me, z, s_near, false);
				}
				return true;
			}
			return false;
		}

		private static bool RingHas(Vector2s z)
		{
			//IL_0000: 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_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)
			int num = Mathf.Max(Mathf.Abs(z.x - s_me.x), Mathf.Abs(z.y - s_me.y));
			if (num <= s_total)
			{
				if (!s_classic && num != 0)
				{
					return ZoneSystem.instance.ZonesWithinRadius(s_me, z, s_total, true);
				}
				return true;
			}
			return false;
		}

		private static bool GameHas(Vector2s z, bool distant)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (!NearHas(z))
			{
				if (distant)
				{
					return RingHas(z);
				}
				return false;
			}
			return true;
		}

		private static void ListGround()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < s_zones.Count; i++)
			{
				Zone zone = s_zones[i];
				zone.Ground.Clear();
				zone.HasGround = false;
			}
			List<Heightmap> allHeightmaps = Heightmap.GetAllHeightmaps();
			for (int j = 0; j < allHeightmaps.Count; j++)
			{
				Heightmap val = allHeightmaps[j];
				if (!((Object)(object)val == (Object)null))
				{
					Zone zone2 = ZoneAt(((Component)val).transform.position);
					MeshRenderer val2 = ((zone2 != null) ? s_heightmapRenderer.Invoke(val) : null);
					if (!((Object)(object)val2 == (Object)null))
					{
						zone2.Ground.Add((Renderer)(object)val2);
						Bounds bounds = ((Renderer)val2).bounds;
						Spans(zone2, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).max.y);
					}
				}
			}
			List<WaterVolume> instances = WaterVolume.Instances;
			for (int k = 0; k < instances.Count; k++)
			{
				WaterVolume val3 = instances[k];
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.m_waterSurface == (Object)null))
				{
					Zone zone3 = ZoneAt(((Component)val3).transform.position);
					if (zone3 != null)
					{
						zone3.Ground.Add((Renderer)(object)val3.m_waterSurface);
						float y = ((Component)val3.m_waterSurface).transform.position.y;
						Spans(zone3, y, y);
					}
				}
			}
		}

		private static void Spans(Zone z, float min, float max)
		{
			if (!z.HasGround)
			{
				z.HasGround = true;
				z.MinY = min;
				z.MaxY = max;
			}
			else
			{
				z.MinY = Mathf.Min(z.MinY, min);
				z.MaxY = Mathf.Max(z.MaxY, max);
			}
		}

		private static void ListLights()
		{
			//IL_005b: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			s_lights.Clear();
			HashSet<LightLod> hashSet = s_lodLights.Invoke();
			if (hashSet == null)
			{
				return;
			}
			if (s_lightDistant.Count > 4096)
			{
				s_lightDistant.Clear();
			}
			foreach (LightLod item in hashSet)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Vector2s zone = ZoneSystem.GetZone(((Component)item).transform.position);
				int index = Index(zone.x, zone.y);
				if (ZoneAt(index) == null)
				{
					continue;
				}
				Light val = s_lodLight.Invoke(item);
				if (!((Object)(object)val == (Object)null))
				{
					if (!s_lightDistant.TryGetValue(item, out var value))
					{
						ZNetView componentInParent = ((Component)item).GetComponentInParent<ZNetView>();
						value = (Object)(object)componentInParent != (Object)null && componentInParent.m_distant;
						s_lightDistant[item] = value;
					}
					s_lights.Add(new LightEntry
					{
						Light = val,
						Index = index,
						Distant = value
					});
				}
			}
		}

		private static void ListLively(RemoteAreas areas)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			s_lively.Clear();
			s_points.Clear();
			float num = 0f;
			for (int i = 0; i < areas.Count; i++)
			{
				Vector2s val = areas.AreaZone(i);
				s_points.Add(ZoneSystem.GetZonePos(val));
				List<Vector2s> list = areas.AreaZones(i);
				int num2 = 0;
				for (int j = 0; j < list.Count; j++)
				{
					num2 = Mathf.Max(num2, Mathf.Max(Mathf.Abs(list[j].x - val.x), Mathf.Abs(list[j].y - val.y)));
				}
				num = Mathf.Max(num, (float)(num2 + 1) * 64f * 1.4143f);
			}
			if (s_points.Count == 0)
			{
				return;
			}
			if (s_particlesOf.Count > 20000)
			{
				s_particlesOf.Clear();
			}
			areas.InstancesNear(s_points, num, s_views, draining: true);
			for (int k = 0; k < s_views.Count; k++)
			{
				ZNetView val2 = s_views[k];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Vector2s zone = ZoneSystem.GetZone(((Component)val2).transform.position);
				int index = Index(zone.x, zone.y);
				if (ZoneAt(index) != null)
				{
					if (!s_particlesOf.TryGetValue(val2, out var value))
					{
						((Component)val2).GetComponentsInChildren<ParticleSystemRenderer>(true, s_particles);
						value = ((s_particles.Count > 0) ? s_particles.ToArray() : s_noParticles);
						s_particles.Clear();
						s_particlesOf[val2] = value;
					}
					if (value.Length != 0)
					{
						ZDO zDO = val2.GetZDO();
						s_lively.Add(new Lively
						{
							Renderers = value,
							Root = ((Component)val2).transform,
							Index = index,
							Distant = ((zDO != null) ? zDO.Distant : val2.m_distant)
						});
					}
				}
			}
			s_views.Clear();
		}

		private static void ListClutter()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			ClutterSystem instance = ClutterSystem.instance;
			GameObject val = (((Object)(object)instance != (Object)null) ? s_grassRoot.Invoke(instance) : null);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)val == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				s_clutter.Clear();
				s_clutterNext.Clear();
				s_clutterCursor = 0;
				s_clutterHas = false;
				return;
			}
			Transform transform = val.transform;
			int childCount = transform.childCount;
			Vector3 position = ((Component)localPlayer).transform.position;
			float num = instance.m_distance + instance.m_grassPatchSize * 0.75f;
			bool num2 = s_clutterHas && Utils.DistanceXZ(position, s_clutterFrom) > instance.m_grassPatchSize;
			s_clutterFrom = position;
			s_clutterHas = true;
			if (num2)
			{
				int num3 = 0;
				for (int i = 0; i < s_clutter.Count; i++)
				{
					Renderer val2 = s_clutter[i];
					if (!((Object)(object)val2 == (Object)null) && !(Utils.DistanceXZ(((Component)val2).transform.position, position) <= num))
					{
						s_clutter[num3++] = val2;
					}
				}
				s_clutter.RemoveRange(num3, s_clutter.Count - num3);
				s_clutterNext.Clear();
				s_clutterCursor = 0;
			}
			int num4 = Mathf.Min(childCount, s_clutterCursor + 256);
			InstanceRenderer val3 = default(InstanceRenderer);
			for (int j = s_clutterCursor; j < num4; j++)
			{
				Transform child = transform.GetChild(j);
				if (!((Component)child).TryGetComponent<InstanceRenderer>(ref val3) && !(Utils.DistanceXZ(child.position, position) <= num))
				{
					((Component)child).GetComponentsInChildren<Renderer>(true, s_renderers);
					s_clutterNext.AddRange(s_renderers);
					s_renderers.Clear();
				}
			}
			s_clutterCursor = num4;
			if (num4 >= childCount)
			{
				List<Renderer> list = s_clutterNext;
				s_clutterNext = s_clutter;
				s_clutter = list;
				s_clutterNext.Clear();
				s_clutterCursor = 0;
			}
		}

		private static void Sweep()
		{
			if (s_parts.Count > 4096)
			{
				foreach (KeyValuePair<ZNetView, Parts> s_part in s_parts)
				{
					if ((Object)(object)s_part.Key == (Object)null)
					{
						s_gone.Add(s_part.Key);
					}
				}
				for (int i = 0; i < s_gone.Count; i++)
				{
					s_parts.Remove(s_gone[i]);
				}
				s_gone.Clear();
			}
			if (s_parts.Count > 60000)
			{
				s_parts.Clear();
			}
		}

		private static void View(Camera cam)
		{
			//IL_0011: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			GeometryUtility.CalculateFrustumPlanes(cam, s_planes);
			Vector3 position = ((Component)cam).transform.position;
			float shadowDistance = QualitySettings.shadowDistance;
			float num = ((WindowLayerCull.Radius > 0f) ? WindowLayerCull.Radius : float.MaxValue);
			int num2 = 0;
			Vector3 val = default(Vector3);
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < s_zones.Count; i++)
			{
				Zone zone = s_zones[i];
				Vector3 zonePos = ZoneSystem.GetZonePos(zone.Id);
				float num3 = (zone.HasGround ? (zone.MinY - 32f) : (-1000f));
				float num4 = (zone.HasGround ? (zone.MaxY + 96f) : 3000f);
				((Vector3)(ref val))..ctor(zonePos.x - 48f, num3, zonePos.z - 48f);
				((Vector3)(ref val2))..ctor(zonePos.x + 48f, num4, zonePos.z + 48f);
				Vector3 val3 = Vector3.Max(val, Vector3.Min(val2, position));
				float num5 = (zone.Distance = Vector3.Distance(position, val3));
				zone.InView = num5 < shadowDistance || InFrustum(val, val2);
				zone.Close = num5 < num;
				if (zone.InView)
				{
					num2++;
				}
			}
			LabZonesInView = num2;
		}

		private static bool InFrustum(Vector3 min, Vector3 max)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			Vector3 val = default(Vector3);
			for (int i = 0; i < s_planes.Length; i++)
			{
				Vector3 normal = ((Plane)(ref s_planes[i])).normal;
				((Vector3)(ref val))..ctor((normal.x >= 0f) ? max.x : min.x, (normal.y >= 0f) ? max.y : min.y, (normal.z >= 0f) ? max.z : min.z);
				if (Vector3.Dot(normal, val) + ((Plane)(ref s_planes[i])).distance < 0f)
				{
					return false;
				}
			}
			return true;
		}

		private static void ListObjects(int version, float now)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			s_watch.Restart();
			int num = 0;
			List<ZDO>[] array = s_objectsBySector.Invoke(ZDOMan.instance);
			ZNetScene instance = ZNetScene.instance;
			while (true)
			{
				Zone zone = NextToList(version, now);
				if (zone == null)
				{
					break;
				}
				if (zone.Cursor < 0)
				{
					zone.Snapshot.Clear();
					zone.Next.Clear();
					List<ZDO> list = ((array != null && zone.Index < array.Length) ? array[zone.Index] : null);
					if (list != null)
					{
						zone.Snapshot.AddRange(list);
					}
					zone.Cursor = 0;
				}
				while (zone.Cursor < zone.Snapshot.Count)
				{
					if (num >= 8 && s_watch.Elapsed.TotalMilliseconds >= 0.25)
					{
						return;
					}
					ZDO val = zone.Snapshot[zone.Cursor++];
					num++;
					if (val == null || val.GetSector() != zone.Id)
					{
						continue;
					}
					ZNetView val2 = instance.FindInstance(val);
					if (!((Object)(object)val2 == (Object)null))
					{
						Parts parts = PartsOf(val2, now);
						if (parts.Renderers.Length != 0)
						{
							zone.Next.Add(new Item
							{
								Parts = parts,
								Distant = val.Distant
							});
							LabListed++;
						}
					}
				}
				List<Item> items = zone.Items;
				zone.Items = zone.Next;
				zone.Next = items;
				zone.Next.Clear();
				zone.Snapshot.Clear();
				zone.Cursor = -1;
				zone.ListedVersion = version;
				zone.ListedAt = now;
			}
		}

		private static Zone NextToList(int version, float now)
		{
			Zone result = null;
			int num = int.MaxValue;
			float num2 = float.MaxValue;
			for (int i = 0; i < s_zones.Count; i++)
			{
				Zone zone = s_zones[i];
				int num3;
				if (zone.Cursor >= 0)
				{
					num3 = 0;
				}
				else
				{
					if (!zone.Close || (zone.ListedVersion == version && !(now - zone.ListedAt >= 2f)))
					{
						continue;
					}
					num3 = (zone.InView ? 1 : 2);
				}
				if (num3 < num || (num3 == num && zone.Distance < num2))
				{
					result = zone;
					num = num3;
					num2 = zone.Distance;
				}
			}
			return result;
		}

		private static Parts PartsOf(ZNetView v, float now)
		{
			if (s_parts.TryGetValue(v, out var value) && now - value.ListedAt < 10f)
			{
				return value;
			}
			if (value == null)
			{
				value = new Parts
				{
					View = v
				};
				s_parts[v] = value;
			}
			value.ListedAt = now;
			Fill(value, v);
			return value;
		}

		private static void Fill(Parts p, ZNetView v)
		{
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			((Component)v).GetComponentsInChildren<Renderer>(true, s_renderers);
			int count = s_renderers.Count;
			Character val = default(Character);
			Rigidbody val2 = default(Rigidbody);
			bool flag = ((Component)v).TryGetComponent<Character>(ref val) || ((Component)v).TryGetComponent<Rigidbody>(ref val2);
			if (!flag && !p.Mover && p.Renderers != null && SameRenderers(p.Renderers, s_renderers))
			{
				s_renderers.Clear();
				return;
			}
			if (p.Renderers == null || p.Renderers.Length != count)
			{
				p.Renderers = (Renderer[])(object)new Renderer[count];
				p.Level = new sbyte[count];
				p.Group = new short[count];
			}
			s_renderers.CopyTo(p.Renderers);
			s_renderers.Clear();
			p.Mover = flag;
			p.Root = (p.Mover ? ((Component)v).transform : null);
			for (int i = 0; i < count; i++)
			{
				p.Level[i] = -1;
				p.Group[i] = -1;
			}
			int num = 0;
			if (!p.Mover && count > 0)
			{
				((Component)v).GetComponentsInChildren<LODGroup>(true, s_groups);
				for (int j = 0; j < s_groups.Count; j++)
				{
					if (num >= 32767)
					{
						break;
					}
					LODGroup val3 = s_groups[j];
					if ((Object)(object)val3 == (Object)null || !val3.enabled)
					{
						continue;
					}
					LOD[] lODs = val3.GetLODs();
					if (lODs.Length == 0)
					{
						continue;
					}
					if (p.GroupAt == null || p.GroupAt.Length <= num)
					{
						Array.Resize(ref p.GroupAt, num + 1);
						Array.Resize(ref p.GroupSize, num + 1);
						Array.Resize(ref p.Heights, num + 1);
					}
					Transform transform = ((Component)val3).transform;
					Vector3 lossyScale = transform.lossyScale;
					p.GroupAt[num] = transform.TransformPoint(val3.localReferencePoint);
					p.GroupSize[num] = val3.size * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
					float[] array = ((p.Heights[num] != null && p.Heights[num].Length == lODs.Length) ? p.Heights[num] : new float[lODs.Length]);
					for (int k = 0; k < lODs.Length && k < 127; k++)
					{
						array[k] = lODs[k].screenRelativeTransitionHeight;
						Renderer[] renderers = lODs[k].renderers;
						if (renderers == null)
						{
							continue;
						}
						for (int l = 0; l < renderers.Length; l++)
						{
							if ((Object)(object)renderers[l] != (Object)null && !s_lodOf.ContainsKey(renderers[l]))
							{
								s_lodOf[renderers[l]] = (num << 8) | k;
							}
						}
					}
					p.Heights[num] = array;
					num++;
				}
				s_groups.Clear();
				if (s_lodOf.Count > 0)
				{
					for (int m = 0; m < count; m++)
					{
						if ((Object)(object)p.Renderers[m] != (Object)null && s_lodOf.TryGetValue(p.Renderers[m], out var value))
						{
							p.Group[m] = (short)(value >> 8);
							p.Level[m] = (sbyte)(value & 0xFF);
						}
					}
					s_lodOf.Clear();
				}
			}
			if (p.GroupAt != null && p.GroupAt.Length != num)
			{
				Array.Resize(ref p.GroupAt, num);
				Array.Resize(ref p.GroupSize, num);
				Array.Resize(ref p.Heights, num);
			}
		}

		private static bool SameRenderers(Renderer[] had, List<Renderer> now)
		{
			if (had.Length != now.Count)
			{
				return false;
			}
			for (int i = 0; i < had.Length; i++)
			{
				if (had[i] != now[i])
				{
					return false;
				}
			}
			return true;
		}

		private static void Apply(Camera cam)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)cam).transform.position;
			float tanHalf = Mathf.Tan(cam.fieldOfView * 0.5f * (MathF.PI / 180f));
			float lodBias = QualitySettings.lodBias;
			int maximumLODLevel = QualitySettings.maximumLODLevel;
			for (int i = 0; i < s_zones.Count; i++)
			{
				Zone zone = s_zones[i];
				if (!zone.Near && zone.InView)
				{
					for (int j = 0; j < zone.Ground.Count; j++)
					{
						Off(zone.Ground[j]);
					}
					if (zone.Close)
					{
						HideObjects(zone, position, tanHalf, lodBias, maximumLODLevel);
					}
				}
			}
			for (int k = 0; k < s_lights.Count; k++)
			{
				LightEntry lightEntry = s_lights[k];
				Zone zone2 = ZoneAt(lightEntry.Index);
				if (zone2 != null && !zone2.Near && (!lightEntry.Distant || !zone2.Ring))
				{
					Light light = lightEntry.Light;
					if ((Object)(object)light != (Object)null && ((Behaviour)light).enabled)
					{
						((Behaviour)light).enabled = false;
						s_off.Add(light);
					}
				}
			}
			for (int l = 0; l < s_lively.Count; l++)
			{
				Lively lively = s_lively[l];
				Zone zone3 = ZoneAt(lively.Index);
				if (zone3 != null && zone3.InView && !zone3.Near && (!lively.Distant || !zone3.Ring) && (Crossing.Count <= 0 || !((Object)(object)lively.Root != (Object)null) || !Crossing.Contains(lively.Root)))
				{
					ParticleSystemRenderer[] renderers = lively.Renderers;
					for (int m = 0; m < renderers.Length; m++)
					{
						Off((Renderer)(object)renderers[m]);
					}
				}
			}
			for (int n = 0; n < s_clutter.Count; n++)
			{
				Off(s_clutter[n]);
			}
			if (FarViewer.FarPuffs.Count > 0)
			{
				HidePuffs();
			}
		}

		private static void HidePuffs()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			SmokeRenderer instance = SmokeRenderer.Instance;
			Dictionary<Vector3Int, List<Smoke>> dictionary = (((Object)(object)instance != (Object)null) ? s_smokeChunks.Invoke(instance) : null);
			Dictionary<Vector3Int, ParticleSystem> dictionary2 = (((Object)(object)instance != (Object)null) ? s_smokeSystems.Invoke(instance) : null);
			if (dictionary == null || dictionary2 == null)
			{
				return;
			}
			HashSet<Smoke> farPuffs = FarViewer.FarPuffs;
			ParticleSystemRenderer r = default(ParticleSystemRenderer);
			foreach (KeyValuePair<Vector3Int, List<Smoke>> item in dictionary)
			{
				List<Smoke> value = item.Value;
				if (value != null && value.Count != 0)
				{
					bool flag = true;
					for (int i = 0; i < value.Count && flag; i++)
					{
						flag = farPuffs.Contains(value[i]);
					}
					if (flag && dictionary2.TryGetValue(item.Key, out var value2) && (Object)(object)value2 != (Object)null && ((Component)value2).TryGetComponent<ParticleSystemRenderer>(ref r))
					{
						Off((Renderer)(object)r);
					}
				}
			}
		}

		private static void HideObjects(Zone z, Vector3 eye, float tanHalf, float bias, int lowest)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			List<Item> items = z.Items;
			for (int i = 0; i < items.Count; i++)
			{
				Item item = items[i];
				Parts parts = item.Parts;
				if ((Object)(object)parts.View == (Object)null)
				{
					continue;
				}
				Renderer[] renderers = parts.Renderers;
				if (parts.Mover)
				{
					if (!((Object)(object)parts.Root == (Object)null) && (Crossing.Count <= 0 || !Crossing.Contains(parts.Root)) && !GameHas(ZoneSystem.GetZone(parts.Root.position), item.Distant))
					{
						for (int j = 0; j < renderers.Length; j++)
						{
							Off(renderers[j]);
						}
					}
				}
				else
				{
					if (item.Distant && z.Ring)
					{
						continue;
					}
					int num = ((parts.GroupAt != null) ? parts.GroupAt.Length : 0);
					if (s_level.Length < num)
					{
						s_level = new int[Mathf.NextPowerOfTwo(num)];
					}
					for (int k = 0; k < num; k++)
					{
						s_level[k] = Pick(parts, k, eye, tanHalf, bias, lowest);
					}
					for (int l = 0; l < renderers.Length; l++)
					{
						int num2 = parts.Group[l];
						if (num2 >= 0)
						{
							int num3 = s_level[num2];
							if (num3 == -100 || Mathf.Abs(parts.Level[l] - num3) > 1)
							{
								continue;
							}
						}
						Off(renderers[l]);
					}
				}
			}
		}

		private static int Pick(Parts p, int g, Vector3 eye, float tanHalf, float bias, int lowest)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			float[] array = p.Heights[g];
			int num = array.Length;
			float num2 = Vector3.Distance(eye, p.GroupAt[g]);
			float num3 = ((num2 > 0.001f && tanHalf > 0f) ? (p.GroupSize[g] / (2f * num2 * tanHalf) * bias) : float.MaxValue);
			for (int i = Mathf.Clamp(lowest, 0, num - 1); i < num; i++)
			{
				if (num3 >= array[i])
				{
					return i;
				}
			}
			if (!(num3 >= array[num - 1] * 0.75f))
			{
				return -100;
			}
			return num - 1;
		}

		private static void Off(Renderer r)
		{
			if (!((Object)(object)r == (Object)null) && !r.forceRenderingOff)
			{
				r.forceRenderingOff = true;
				s_hidden.Add(r);
			}
		}
	}
	internal static class DebugDump
	{
		private static readonly Color Magenta = new Color(1f, 0f, 1f, 1f);

		internal static string Write(PortalRenderer renderer, Camera main, List<PortalWindow> windows)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_055a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0576: Unknown result type (might be due to invalid IL or missing references)
			PortalWindow portalWindow = (from x in windows
				where x.Enabled && x.Partner != null
				orderby Vector3.Distance(x.Frame.Center, ((Component)main).transform.position)
				select x).FirstOrDefault();
			if (portalWindow == null)
			{
				Plugin.Log.LogInfo((object)"Debug dump: no live portal window");
				return null;
			}
			string text = Path.Combine(Paths.BepInExRootPath, "RealPortalDebug", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
			Directory.CreateDirectory(text);
			int num = Mathf.Max(64, main.pixelWidth / 2);
			int num2 = Mathf.Max(64, main.pixelHeight / 2);
			RenderTexture val = new RenderTexture(num, num2, 24, (RenderTextureFormat)0)
			{
				antiAliasing = 1
			};
			val.Create();
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				Vector3 val2 = PortalRenderer.ViewPosition(portalWindow, ((Component)main).transform.position);
				object[] obj = new object[5]
				{
					((Component)main).transform.position,
					null,
					null,
					null,
					null
				};
				Quaternion rotation = ((Component)main).transform.rotation;
				obj[1] = ((Quaternion)(ref rotation)).eulerAngles;
				obj[2] = main.fieldOfView;
				obj[3] = main.nearClipPlane;
				obj[4] = main.actualRenderingPath;
				stringBuilder.AppendLine(string.Format("main camera {0} rot {1}, fov {2}, near {3}, path {4}", obj));
				stringBuilder.AppendLine($"entry centre {portalWindow.Frame.Center} fwd {portalWindow.Frame.Forward}; exit centre {portalWindow.Partner.Frame.Center} fwd {portalWindow.Partner.Frame.Forward}");
				stringBuilder.AppendLine($"window camera {val2}, {portalWindow.Partner.Frame.SignedDistance(val2):0.00} m from the exit plane");
				if ((Object)(object)ZoneSystem.instance != (Object)null)
				{
					stringBuilder.AppendLine($"ground under window camera {ZoneSystem.instance.GetGroundHeight(val2):0.00}, liquid {Floating.GetLiquidLevel(val2, 1f, (LiquidType)10):0.00}");
				}
				stringBuilder.AppendLine($"settings: path {renderer.Settings.RenderingPath}, clear {renderer.Settings.ClearFlags}, far {renderer.Settings.FarClip}, " + $"res {renderer.Settings.Resolution}, pixel lights {QualitySettings.pixelLightCount}");
				renderer.RenderDebug(main, windows, portalWindow, val, main.cullingMask, null);
				Save(val, Path.Combine(text, "view.png"), out var _);
				WriteLive(renderer, main, windows, portalWindow, text, stringBuilder);
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("layers drawn in the window (pixels not magenta):");
				for (int num3 = 0; num3 < 32; num3++)
				{
					string arg = LayerMask.LayerToName(num3);
					if ((main.cullingMask & (1 << num3)) != 0)
					{
						renderer.RenderDebug(main, windows, portalWindow, val, 1 << num3, Magenta);
						Read(val, out var tex2);
						int num4 = tex2.GetPixels32().Count((Color32 c) => c.r <= 250 || c.g >= 5 || c.b <= 250);
						if (num4 > 0)
						{
							File.WriteAllBytes(Path.Combine(text, $"layer_{num3:00}_{arg}.png"), ImageConversion.EncodeToPNG(tex2));
							stringBuilder.AppendLine($"  {num3,2} {arg,-20} {100f * (float)num4 / (float)(num * num2):0.0}%");
						}
						Object.Destroy((Object)(object)tex2);
					}
				}
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("renderers within 40 m of the window camera on the camera side of the exit plane (should be clipped):");
				foreach (string item in BehindExit(portalWindow, val2))
				{
					stringBuilder.AppendLine("  " + item);
				}
			}
			catch (Exception ex)
			{
				stringBuilder.AppendLine("ERROR " + ex);
			}
			finally
			{
				val.Release();
				Object.Destroy((Object)(object)val);
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("window camera components and command buffers:");
			Behaviour[] components = ((Component)renderer.Camera).GetComponents<Behaviour>();
			foreach (Behaviour val3 in components)
			{
				stringBuilder.AppendLine($"  component {((object)val3).GetType().FullName} enabled {val3.enabled}");
			}
			foreach (CameraEvent value in Enum.GetValues(typeof(CameraEvent)))
			{
				CommandBuffer[] commandBuffers = renderer.Camera.GetCommandBuffers(value);
				foreach (CommandBuffer val5 in commandBuffers)
				{
					stringBuilder.AppendLine($"  {(object)value}: {val5.name}");
				}
			}
			File.WriteAllText(Path.Combine(text, "info.txt"), stringBuilder.ToString());
			Plugin.Log.LogInfo((object)("Debug dump written to " + text));
			return text;
		}

		internal static void LiveFrame(Camera main, List<PortalWindow> windows, string dir, int index)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			PortalWindow portalWindow = (from x in windows
				where x.Enabled && x.Partner != null && x.RenderedThisFrame && (Object)(object)x.Texture != (Object)null
				orderby Vector3.Distance(x.Frame.Center, ((Component)main).transform.position)
				select x).FirstOrDefault();
			if (portalWindow != null)
			{
				RenderTexture val = new RenderTexture(((Texture)portalWindow.Texture).width, ((Texture)portalWindow.Texture).height, 0, (RenderTextureFormat)0);
				val.Create();
				Graphics.Blit((Texture)(object)portalWindow.Texture, val);
				Save(val, Path.Combine(dir, $"window_frame{index}_f{Time.frameCount}.png"), out var _);
				val.Release();
				Object.Destroy((Object)(object)val);
			}
		}

		private static void WriteLive(PortalRenderer renderer, Camera main, List<PortalWindow> windows, PortalWindow w, string dir, StringBuilder info)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (!w.RenderedThisFrame || (Object)(object)w.Texture == (Object)null)
			{
				info.AppendLine("live window texture: not rendered this frame");
				return;
			}
			RenderTexture texture = w.Texture;
			Rect textureRect = w.TextureRect;
			info.AppendLine($"live window texture {((Texture)texture).width}x{((Texture)texture).height} {texture.format}, screen rect {textureRect}");
			RenderTexture val = new RenderTexture(((Texture)texture).width, ((Texture)texture).height, 24, (RenderTextureFormat)0)
			{
				antiAliasing = 1
			};
			val.Create();
			try
			{
				Graphics.Blit((Texture)(object)texture, val);
				Save(val, Path.Combine(dir, "window_live.png"), out var tex);
				renderer.RenderDebug(main, windows, w, val, main.cullingMask, null, textureRect, 0f);
				Save(val, Path.Combine(dir, "window_noshadows.png"), out tex);
				renderer.RenderDebug(main, windows, w, val, main.cullingMask, null, textureRect, QualitySettings.shadowDistance);
				Save(val, Path.Combine(dir, "window_shadows.png"), out tex);
			}
			finally
			{
				val.Release();
				Object.Destroy((Object)(object)val);
			}
		}

		private static IEnumerable<string> BehindExit(PortalWindow w, Vector3 camPos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			PortalFrame exit = w.Partner.Frame;
			float camSide = Mathf.Sign(exit.SignedDistance(camPos));
			return Object.FindObjectsByType<Renderer>((FindObjectsSortMode)0).Where(delegate(Renderer r)
			{
				//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_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				if (r.enabled && ((Component)r).gameObject.activeInHierarchy)
				{
					Bounds bounds = r.bounds;
					if (((Bounds)(ref bounds)).SqrDistance(camPos) < 1600f)
					{
						PortalFrame portalFrame = exit;
						bounds = r.bounds;
						return Mathf.Sign(portalFrame.SignedDistance(((Bounds)(ref bounds)).center)) == camSide;
					}
				}
				return false;
			}).OrderBy(delegate(Renderer r)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				Bounds bounds = r.bounds;
				return ((Bounds)(ref bounds)).SqrDistance(camPos);
			})
				.Take(40)
				.Select(delegate(Renderer r)
				{
					//IL_0082: Unknown result type (might be due to invalid IL or missing references)
					//IL_0087: Unknown result type (might be due to invalid IL or missing references)
					//IL_008b: Unknown result type (might be due to invalid IL or missing references)
					string[] obj = new string[7]
					{
						NameOf(((Component)r).transform),
						" layer ",
						LayerMask.LayerToName(((Component)r).gameObject.layer),
						", shader ",
						((Object)(object)r.sharedMaterial != (Object)null && (Object)(object)r.sharedMaterial.shader != (Object)null) ? ((Object)r.sharedMaterial.shader).name : "none",
						", ",
						null
					};
					Bounds bounds = r.bounds;
					obj[6] = $"{Mathf.Sqrt(((Bounds)(ref bounds)).SqrDistance(camPos)):0.0} m";
					return string.Concat(obj);
				});
		}

		private static string NameOf(Transform t)
		{
			if (!((Object)(object)t.parent != (Object)null))
			{
				return ((Object)t).name;
			}
			return ((Object)t.parent).name + "/" + ((Object)t).name;
		}

		private static void Read(RenderTexture rt, out Texture2D tex)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = rt;
			tex = new Texture2D(((Texture)rt).width, ((Texture)rt).height, (TextureFormat)3, false);
			tex.ReadPixels(new Rect(0f, 0f, (float)((Texture)rt).width, (float)((Texture)rt).height), 0, 0);
			tex.Apply();
			RenderTexture.active = active;
		}

		private static void Save(RenderTexture rt, string path, out Texture2D tex)
		{
			Read(rt, out tex);
			File.WriteAllBytes(path, ImageConversion.EncodeToPNG(tex));
			Object.Destroy((Object)(object)tex);
		}
	}
	[HarmonyPatch]
	internal static class FarDrain
	{
		internal static int LabQuietPokes;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainModifier), "PokeHeightmaps")]
		private static bool PokeHeightmaps(TerrainModifier __instance, bool forcedDelay)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!FarFlags.DrainCalm || forcedDelay)
			{
				return true;
			}
			RemoteAreas remoteAreas = PortalSystem.Instance?.Areas;
			if (remoteAreas == null || !remoteAreas.UnloadsQuietly(((Component)__instance).transform.position))
			{
				return true;
			}
			LabQuietPokes++;
			return false;
		}
	}
	internal static class FarHeightmaps
	{
		private const float GoneSeconds = 120f;

		private const float RefreshSeconds = 1f;

		internal static readonly Func<Vector3, Place> Hook = PlaceOf;

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

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

		private static readonly List<Vector2s> s_live = new List<Vector2s>();

		private static int s_liveReach;

		private static int s_near;

		private static int s_whole;

		private static int s_areaNear;

		private static RemoteAreas s_areas;

		private static int s_version = -1;

		private static float s_refreshAt;

		private static int s_meFrame = -1;

		private static Vector2s s_me;

		internal static long LabNear;

		internal static long LabFar;

		internal static long LabUnloading;

		internal static void Switched()
		{
			HeightmapIdleModule.PlaceOf = ((FarFlags.HeightmapDrainSkip || FarFlags.FarRegenBudget) ? Hook : null);
			HeightmapIdleModule.ForgetPlaces();
		}

		private static Place PlaceOf(Vector3 at)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			bool heightmapDrainSkip = FarFlags.HeightmapDrainSkip;
			bool farRegenBudget = FarFlags.FarRegenBudget;
			ZNet instance = ZNet.instance;
			if ((heightmapDrainSkip || farRegenBudget) && !((Object)(object)instance == (Object)null) && !((Object)(object)ZoneSystem.instance == (Object)null))
			{
				int frameCount = Time.frameCount;
				if (frameCount != s_meFrame)
				{
					s_meFrame = frameCount;
					s_me = ZoneSystem.GetZone(instance.GetReferencePosition());
				}
				RemoteAreas remoteAreas = PortalSystem.Instance?.Areas;
				float time = Time.time;
				if (remoteAreas != s_areas || (remoteAreas != null && remoteAreas.AreasVersion != s_version) || !(time < s_refreshAt))
				{
					Refresh(remoteAreas, instance, time);
				}
				Vector2s zone = ZoneSystem.GetZone(at);
				int num = Distance(zone, s_me);
				if (num <= s_near)
				{
					LabNear++;
					return (Place)0;
				}
				if (heightmapDrainSkip && num > s_whole && s_unloading.Count > 0 && s_unloading.ContainsKey(Key(zone)) && !Live(zone))
				{
					LabUnloading++;
					return (Place)2;
				}
				if (!farRegenBudget || Simulated(remoteAreas, zone) || (FarFlags.VisibleNear && remoteAreas != null && remoteAreas.ShowsZone(zone)))
				{
					LabNear++;
					return (Place)0;
				}
				LabFar++;
				return (Place)1;
			}
			return (Place)0;
		}

		private static void Refresh(RemoteAreas areas, ZNet net, float now)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (areas != s_areas)
			{
				s_unloading.Clear();
			}
			s_areas = areas;
			s_version = areas?.AreasVersion ?? (-1);
			s_refreshAt = now + 1f;
			ZoneSystem instance = ZoneSystem.instance;
			s_next.Clear();
			foreach (KeyValuePair<int, float> item in s_unloading)
			{
				if (now - item.Value < 120f && now >= item.Value && instance.IsZoneLoaded(Unkey(item.Key)))
				{
					s_next[item.Key] = item.Value;
				}
			}
			s_live.Clear();
			if (areas != null)
			{
				for (int i = 0; i < areas.Count; i++)
				{
					if (!areas.AreaDraining(i))
					{
						s_live.Add(areas.AreaZone(i));
						continue;
					}
					List<Vector2s> list = areas.AreaZones(i);
					for (int j = 0; j < list.Count; j++)
					{
						s_next[Key(list[j])] = now;
					}
				}
			}
			Dictionary<int, float> dictionary = s_unloading;
			s_unloading = s_next;
			s_next = dictionary;
			s_next.Clear();
			SimulationDistance syncedSimulationDistance = net.GetSyncedSimulationDistance();
			s_near = ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance + 1;
			s_whole = ((SimulationDistance)(ref syncedSimulationDistance)).TotalSimulationDistance + 1;
			SimulationDistance val = RemoteAreas.AreaDistance();
			s_liveReach = ((SimulationDistance)(ref val)).TotalSimulationDistance;
			s_areaNear = ((SimulationDistance)(ref val)).NearSimulationDistance + 1;
		}

		private static bool Live(Vector2s zone)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < s_live.Count; i++)
			{
				if (Distance(zone, s_live[i]) <= s_liveReach)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Simulated(RemoteAreas areas, Vector2s zone)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (areas == null)
			{
				return false;
			}
			for (int i = 0; i < areas.Count; i++)
			{
				if (areas.AreaSimulated(i) && Distance(zone, areas.AreaZone(i)) <= s_areaNear)
				{
					return true;
				}
			}
			return false;
		}

		private static int Distance(Vector2s a, Vector2s b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return Math.Max(Math.Abs(a.x - b.x), Math.Abs(a.y - b.y));
		}

		private static int Key(Vector2s zone)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (zone.x << 16) | (ushort)zone.y;
		}

		private static Vector2s Unkey(int key)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2s((short)(key >> 16), (short)key);
		}
	}
	internal static class FarEnvironment
	{
		private sealed class Flash
		{
			public Light[] Lights;

			public Renderer[] Renderers;
		}

		private sealed class Shadow
		{
			public float Until;

			public EnvSetup Env;

			public Matrix4x4 ToFar;

			public Vector3 Place;

			public FollowPlayer Follower;

			public readonly List<Mover> Movers = new List<Mover>();

			public GameObject Go;

			public GameObject Original;

			public Place Owner;

			public ParticleSystem[] Systems;

			public bool Clone;

			public bool Wanted;

			public bool Fading;

			public float FadeUntil;
		}

		private sealed class Mover
		{
			public Transform T;

			public FollowPlayer Follower;

			public Vector3 Local;

			public readonly List<(ParticleSystem ps, ParticleSystemSimulationSpace space, Transform custom)> Systems = new List<(ParticleSystem, ParticleSystemSimulationSpace, Transform)>();
		}

		private sealed class Storm
		{
			public Thunder T;

			public Matrix4x4 ToFar;

			public EnvSetup Env;

			public float Until;

			public float NextAt;

			public float ThunderAt = -1f;

			public Vector3 FlashAt;

			public readonly List<GameObject> Flashes = new List<GameObject>();
		}

		private sealed class Place
		{
			public Vector3 At;

			public Matrix4x4 ToFar;

			public float SeenAt = -100f;

			public float CheckAt;

			public int Frame = -1;

			public long Period = long.MinValue;

			public bool Watched;

			public EnvSetup Override;

			public bool Sheltered;

			public EnvSetup Target;

			public EnvSetup From;

			public EnvSetup Mix;

			public EnvSetup MixFrom;

			public float BlendAt;

			public float T;

			public EnvSetup Systems;

			public bool Running;

			public bool Starting;

			public readonly List<Shadow> Shadows = new List<Shadow>();

			public Storm Storm;
		}

		private sealed class WeatherClone
		{
			public GameObject Original;

			public GameObject Go;

			public float FreeAt;
		}

		private static readonly FieldRef<EnvMan, EnvSetup> s_current = AccessTools.FieldRefAccess<EnvMan, EnvSetup>("m_currentEnv");

		private static readonly FieldRef<EnvMan, EnvSetup> s_next = AccessTools.FieldRefAccess<EnvMan, EnvSetup>("m_nextEnv");

		private static readonly FieldRef<EnvMan, string> s_forceEnv = AccessTools.FieldRefAccess<EnvMan, string>("m_forceEnv");

		private static readonly FieldRef<EnvMan, float> s_smoothDay = AccessTools.FieldRefAccess<EnvMan, float>("m_smoothDayFraction");

		private static readonly Func<EnvMan, List<EnvEntry>, EnvSetup> s_select = AccessTools.MethodDelegate<Func<EnvMan, List<EnvEntry>, EnvSetup>>(AccessTools.Method(typeof(EnvMan), "SelectWeightedEnvironment", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<EnvMan, string, EnvSetup> s_getEnv = AccessTools.MethodDelegate<Func<EnvMan, string, EnvSetup>>(AccessTools.Method(typeof(EnvMan), "GetEnv", (Type[])null, (Type[])null), (object)null, true);

		private static readonly int s_skyboxSunDir = Shader.PropertyToID("_SkyboxSunDir");

		private static readonly int s_sunDir = Shader.PropertyToID("_SunDir");

		private static readonly int s_sunFogColor = Shader.PropertyToID("_SunFogColor");

		private static readonly int s_sunColor = Shader.PropertyToID("_SunColor");

		private static readonly int s_ambientColor = Shader.PropertyToID("_AmbientColor");

		private static readonly int s_wet = Shader.PropertyToID("_Wet");

		private static readonly int s_aurora = Shader.PropertyToID("_AuroraStrength");

		private static readonly int s_rain = Shader.PropertyToID("_Rain");

		private static readonly int s_opacity = Shader.PropertyToID("_Opacity");

		private static float s_day;

		private static float s_night;

		private static float s_morning;

		private static float s_evening;

		private static bool s_have;

		private static bool s_applied;

		private static Quaternion s_lightRot;

		private static float s_lightIntensity;

		private static Color s_lightColor;

		private static Color s_fogColor;

		private static Color s_ambient;

		private static Color s_sunFog;

		private static Color s_sunCol;

		private static Color s_ambientGlobal;

		private static float s_fogDensity;

		private static float s_wetValue;

		private static float s_auroraValue;

		private static float s_rainValue;

		private static float s_opacityValue;

		private static Vector4 s_skyDir;

		private static Vector4 s_sunDirValue;

		private static long s_cachePeriod = -1L;

		private static readonly Dictionary<Vector2s, EnvSetup> s_cache = new Dictionary<Vector2s, EnvSetup>();

		private static string s_forcedName;

		private static EnvSetup s_forcedEnv;

		internal static string LabLastPick = "";

		internal static string LabFarEnv;

		private static EnvSetup s_swapEnv;

		private static float s_labSetAt;

		internal static int LabSwaps;

		private static readonly FieldRef<EnvMan, GameObject[]> s_currentPSystems = AccessTools.FieldRefAccess<EnvMan, GameObject[]>("m_currentPSystems");

		private static readonly FieldRef<EnvMan, float> s_instantTimer = AccessTools.FieldRefAccess<EnvMan, float>("m_forceInstantEnvSwitchTimer");

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

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

		private static readonly Dictionary<GameObject, Flash> s_flashParts = new Dictionary<GameObject, Flash>();

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

		private static readonly FieldRef<EnvMan, GameObject> s_envObject = AccessTools.FieldRefAccess<EnvMan, GameObject>("m_currentEnvObject");

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

		private static readonly List<Light> s_offLights = new List<Light>();

		internal static bool InStrike;

		private static readonly Dictionary<GameObject, Renderer[]> s_renderers = new Dictionary<GameObject, Renderer[]>();

		private static readonly int s_wind1 = Shader.PropertyToID("_GlobalWind1");

		private static readonly int s_wind2 = Shader.PropertyToID("_GlobalWind2");

		private static readonly int s_windForce = Shader.PropertyToID("_GlobalWindForce");

		private static Vector4 s_wind1Value;

		private static Vector4 s_wind2Value;

		private static Vector4 s_windForceValue;

		private static bool s_windSet;

		private static readonly Dictionary<GameObject, Shadow> s_shadow = new Dictionary<GameObject, Shadow>();

		private static readonly Dictionary<GameObject, (EnvSetup env, Matrix4x4 toFar, Vector3 place)> s_wanted = new Dictionary<GameObject, (EnvSetup, Matrix4x4, Vector3)>();

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

		private static readonly Dictionary<GlobalWind, GameObject[]> s_windChain = new Dictionary<GlobalWind, GameObject[]>();

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

		private static readonly FieldRef<EnvMan, float> s_wetDuration = AccessTools.FieldRefAccess<EnvMan, float>("m_wetTransitionDuration");

		private static readonly List<(Vector3 place, float wet, float seenAt)> s_farWet = new List<(Vector3, float, float)>();

		private static readonly FieldInfo s_isWet = AccessTools.Field(typeof(EnvMan), "s_isWet");

		private static readonly FieldInfo s_isCold = AccessTools.Field(typeof(EnvMan), "s_isCold");

		private static readonly FieldInfo s_isFreezing = AccessTools.Field(typeof(EnvMan), "s_isFreezing");

		private static readonly Dictionary<Thunder, Storm> s_storms = new Dictionary<Thunder, Storm>();

		private static readonly List<Thunder> s_stormDrop = new List<Thunder>();

		private static readonly List<Light> s_onLights = new List<Light>();

		internal static int LabFarFlashes;

		internal static int LabFlashesShown;

		internal static int LabFarThunders;

		internal static EnvSetup Setting;

		private static readonly FieldRef<EnvMan, Vector4> s_windDir1 = AccessTools.FieldRefAccess<EnvMan, Vector4>("m_windDir1");

		private static readonly FieldRef<EnvMan, Vector4> s_windDir2 = AccessTools.FieldRefAccess<EnvMan, Vector4>("m_windDir2");

		private static readonly FieldRef<EnvMan, Vector4> s_windNow = AccessTools.FieldRefAccess<EnvMan, Vector4>("m_wind");

		private static readonly Action<EnvMan, float> s_updateWindTransition = AccessTools.MethodDelegate<Action<EnvMan, float>>(AccessTools.Method(typeof(EnvMan), "UpdateWindTransition", new Type[1] { typeof(float) }, (Type[])null), (object)null, true);

		internal static string LabLastSet = "";

		internal static string LabApplied;

		private static readonly Action<EnvMan, long, BiomeSector> s_updateEnvironment = AccessTools.MethodDelegate<Action<EnvMan, long, BiomeSector>>(AccessTools.Method(typeof(EnvMan), "UpdateEnvironment", new Type[2]
		{
			typeof(long),
			typeof(BiomeSector)
		}, (Type[])null), (object)null, true);

		private static readonly Func<EnvMan, BiomeSector> s_getBiome = AccessTools.MethodDelegate<Func<EnvMan, BiomeSector>>(AccessTools.Method(typeof(EnvMan), "GetBiome", Type.EmptyTypes, (Type[])null), (object)null, true);

		private static readonly Action<EnvMan, float> s_interpolate = AccessTools.MethodDelegate<Action<EnvMan, float>>(AccessTools.Method(typeof(EnvMan), "InterpolateEnvironment", new Type[1] { typeof(float) }, (Type[])null), (object)null, true);

		private static readonly Action<EnvMan, EnvSetup, float, float, float, float, float> s_setEnv = AccessTools.MethodDelegate<Action<EnvMan, EnvSetup, float, float, float, float, float>>(AccessTools.Method(typeof(EnvMan), "SetEnv", new Type[6]
		{
			typeof(EnvSetup),
			typeof(float),
			typeof(float),
			typeof(float),
			typeof(float),
			typeof(float)
		}, (Type[])null), (object)null, true);

		private static readonly List<Place> s_places = new List<Place>();

		private static readonly List<WeatherClone> s_clones = new List<WeatherClone>();

		private static readonly Dictionary<GameObject, bool> s_cloneable = new Dictionary<GameObject, bool>();

		private static readonly Dictionary<GameObject, Place> s_handTo = new Dictionary<GameObject, Place>();

		private static readonly Collider[] s_zoneHits = (Collider[])(object)new Collider[32];

		private static int s_placeStates;

		private static bool s_parityRuns;

		private static bool s_placeSwapped;

		private static Place s_swapPlace;

		private static EnvSetup s_swapKeyEnv;

		private const int MaxClones = 16;

		private const float CloneKeep = 300f;

		private const float FadeMax = 20f;

		private const int ChecksPerFrame = 2;

		private static int s_checkFrame = -1;

		private static int s_checks;

		private static bool s_overrideWarned;

		internal static int LabPlaceOverrides;

		internal static int LabPlaceSheltered;

		internal static long LabPlaceBlends;

		internal static long LabWeatherClones;

		private static readonly FieldRef<EnvMan, long> s_envPeriod = AccessTools.FieldRefAccess<EnvMan, long>("m_environmentPeriod");

		private static readonly FieldRef<RandEventSystem, RandomEvent> s_randomEvent = AccessTools.FieldRefAccess<RandEventSystem, RandomEvent>("m_randomEvent");

		private static readonly FieldRef<RandEventSystem, RandomEvent> s_forcedEvent = AccessTools.FieldRefAccess<RandEventSystem, RandomEvent>("m_forcedEvent");

		private static readonly int s_auroraCurrent = Shader.PropertyToID("_AuroraGradientCurrent");

		private static readonly int s_auroraNext = Shader.PropertyToID("_AuroraGradientNext");

		private static readonly int s_auroraBlend = Shader.PropertyToID("_AuroraGradientBlend");

		private static bool s_auroraSet;

		private static Texture s_auroraGameCur;

		private static Texture s_auroraGameNext;

		private static Texture s_auroraCur;

		private static Texture s_auroraNextNow;

		private static float s_auroraGameBlend;

		private static float s_auroraBlendNow;

		internal static bool HasFarState
		{
			get
			{
				if (s_shadow.Count <= 0 && s_storms.Count <= 0 && s_farWet.Count <= 0)
				{
					return s_places.Count > 0;
				}
				return true;
			}
		}

		internal static float DayFraction
		{
			get
			{
				if (!((Object)(object)EnvMan.instance != (Object)null))
				{
					return 0f;
				}
				return s_smoothDay.Invoke(EnvMan.instance);
			}
		}

		internal static EnvSetup Applied { get; private set; }

		internal static string GameEnvName
		{
			get
			{
				EnvMan instance = EnvMan.instance;
				return (((Object)(object)instance != (Object)null) ? s_current.Invoke(instance) : null)?.m_name;
			}
		}

		internal static bool OwnFlashing
		{
			get
			{
				for (int i = 0; i < s_flashes.Count; i++)
				{
					if ((Object)(object)s_flashes[i] != (Object)null)
					{
						return true;
					}
				}
				return false;
			}
		}

		internal static void Capture(float day, float night, float morning, float evening)
		{
			s_day = day;
			s_night = night;
			s_morning = morning;
			s_evening = evening;
			s_have = true;
		}

		internal static EnvSetup Pick(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Pick(pos, places: true);
		}

		private static EnvSetup Pick(Vector3 pos, bool places, Place view = null)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || WorldGenerator.instance == null || (Object)(object)ZNet.instance == (Object)null || instance.m_environmentDuration <= 0)
			{
				return null;
			}
			if (!string.IsNullOrEmpty(LabFarEnv))
			{
				EnvSetup val = s_getEnv(instance, LabFarEnv);
				EnvSetup val2 = s_current.Invoke(instance);
				if (val == null || (val2 != null && !(val2.m_name != val.m_name)))
				{
					return null;
				}
				return val;
			}
			bool weatherParity = FarFlags.WeatherParity;
			if (!weatherParity)
			{
				if (!string.IsNullOrEmpty(instance.m_debugEnv) || !string.IsNullOrEmpty(s_forceEnv.Invoke(instance)))
				{
					return null;
				}
			}
			else if (!string.IsNullOrEmpty(instance.m_debugEnv) || ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).InIntro()))
			{
				return null;
			}
			long period = (long)ZNet.instance.GetTimeSeconds() / instance.m_environmentDuration;
			EnvSetup val3 = ZonePick(instance, pos, period);
			if (!weatherParity)
			{
				EnvSetup val4 = s_current.Invoke(instance);
				if (val3 == null || (val4 != null && val4.m_name == val3.m_name && s_next.Invoke(instance) == null))
				{
					return null;
				}
				return val3;
			}
			Place place = ((places && s_placeStates > 0) ? (view ?? PlaceNear(pos)) : null);
			if (place != null && place.Override != null)
			{
				val3 = place.Override;
			}
			if (val3 == null)
			{
				return null;
			}
			if (place != null && place.From != null && place.Target == val3)
			{
				return val3;
			}
			bool forced;
			EnvSetup val5 = GameEnv(instance, out forced);
			if (val5 != null && val5.m_name == val3.m_name && (forced || s_next.Invoke(instance) == null))
			{
				return null;
			}
			return val3;
		}

		private static EnvSetup ZonePick(EnvMan em, Vector3 pos, long period)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Vector2s zone = ZoneSystem.GetZone(pos);
			if (period != s_cachePeriod)
			{
				s_cachePeriod = period;
				s_cache.Clear();
			}
			if (!s_cache.TryGetValue(zone, out var value))
			{
				value = (s_cache[zone] = PickNow(em, pos, period));
			}
			return value;
		}

		private static EnvSetup GameEnv(EnvMan em, out bool forced)
		{
			string text = s_forceEnv.Invoke(em);
			forced = !string.IsNullOrEmpty(text);
			if (!forced)
			{
				return s_current.Invoke(em);
			}
			if ((object)text != s_forcedName)
			{
				s_forcedName = text;
				s_forcedEnv = s_getEnv(em, text);
			}
			return s_forcedEnv;
		}

		private static EnvSetup PickNow(EnvMan em, Vector3 pos, long period)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			EnvSetup val = PickNowInner(em, pos, period);
			LabLastPick = string.Format("{0} for {1} period {2}", (val != null) ? val.m_name : "none", WorldGenerator.instance.GetBiomeSector(pos, false).Biome, period);
			return val;
		}

		private static EnvSetup PickNowInner(EnvMan em, Vector3 pos, long period)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			BiomeSector biomeSector = WorldGenerator.instance.GetBiomeSector(pos, false);
			foreach (AltBiome altBiome in biomeSector.AltBiomes)
			{
				if (!string.IsNullOrEmpty(altBiome.m_forceEnvironment))
				{
					return s_getEnv(em, altBiome.m_forceEnvironment);
				}
			}
			bool flag = WorldGenerator.IsAshlands(pos.x, pos.z);
			bool flag2 = WorldGenerator.IsDeepnorth(pos.x, pos.y);
			State state = Random.state;
			Random.InitState((int)period);
			EnvSetup result = null;
			List<EnvEntry> availableEnvironments = em.GetAvailableEnvironments(biomeSector);
			if (availableEnvironments != null && availableEnvironments.Count > 0)
			{
				result = s_select(em, availableEnvironments);
				foreach (EnvEntry item in availableEnvironments)
				{
					if (item.m_ashlandsOverride && flag)
					{
						result = item.m_env;
					}
					if (item.m_deepnorthOverride && flag2)
					{
						result = item.m_env;
					}
				}
			}
			Random.state = state;
			return result;
		}

		internal static void Apply(Vector3 camPos)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (WindowFlags.EnvGroups && !s_applied)
			{
				ApplyGrouped(camPos);
			}
			else
			{
				ApplyOne(camPos);
			}
		}

		private static void ApplyOne(Vector3 camPos)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			if (s_applied || !s_have || (Object)(object)instance == (Object)null || (Object)(object)instance.m_dirLight == (Object)null)
			{
				return;
			}
			Place place = (FarFlags.WeatherParity ? ViewPlace(camPos) : null);
			EnvSetup val = Pick(camPos, places: true, place);
			if (val == null && (place == null || !PlaceDiffers(instance, place)))
			{
				return;
			}
			Light dirLight = instance.m_dirLight;
			s_applied = true;
			s_lightRot = ((Component)dirLight).transform.rotation;
			s_lightIntensity = dirLight.intensity;
			s_lightColor = dirLight.color;
			s_fogColor = RenderSettings.fogColor;
			s_fogDensity = RenderSettings.fogDensity;
			s_ambient = RenderSettings.ambientLight;
			s_skyDir = Shader.GetGlobalVector(s_skyboxSunDir);
			s_sunDirValue = Shader.GetGlobalVector(s_sunDir);
			s_sunFog = Shader.GetGlobalColor(s_sunFogColor);
			s_sunCol = Shader.GetGlobalColor(s_sunColor);
			s_ambientGlobal = Shader.GetGlobalColor(s_ambientColor);
			s_wetValue = Shader.GetGlobalFloat(s_wet);
			s_auroraValue = Shader.GetGlobalFloat(s_aurora);
			Material val2 = (((Object)(object)instance.m_clouds != (Object)null) ? ((Renderer)instance.m_clouds).sharedMaterial : null);
			if ((Object)(object)val2 != (Object)null)
			{
				s_rainValue = val2.GetFloat(s_rain);
				s_opacityValue = val2.GetFloat(s_opacity);
			}
			bool weatherParity = FarFlags.WeatherParity;
			if (val == null)
			{
				SwapPlace(instance, null, place);
				return;
			}
			EnvSetup val3 = (weatherParity ? LookOf(place, val) : val);
			Set(instance, val3, WetAt(place?.At ?? camPos, val));
			if (weatherParity)
			{
				Aurora(place, val);
			}
			LabApplied = val.m_name;
			Applied = val3;
			SetWind(instance, val3);
			if (weatherParity)
			{
				SwapPlace(instance, val, place);
			}
			else
			{
				SwapWeather(instance, val);
			}
		}

		private static void ApplyGrouped(Vector3 camPos)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			if (!s_have || (Object)(object)instance == (Object)null || (Object)(object)instance.m_dirLight == (Object)null)
			{
				return;
			}
			bool weatherParity = FarFlags.WeatherParity;
			Place place = (weatherParity ? ViewPlace(camPos) : null);
			EnvSetup val = Pick(camPos, places: true, place);
			if (val == null)
			{
				AreaRenderState.ToGame(instance);
				AuroraBack();
				if (place != null && PlaceDiffers(instance, place))
				{
					if (!s_placeSwapped || s_swapPlace != place |

plugins/RealPortalEngine.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("RealPortalEngine")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RealPortalEngine")]
[assembly: AssemblyTitle("RealPortalEngine")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace RealPortal
{
	public static class Features
	{
		private static readonly Dictionary<string, Feature> s_byName = new Dictionary<string, Feature>(StringComparer.OrdinalIgnoreCase);

		private static ConfigFile s_config;

		public static IEnumerable<Feature> All => s_byName.Values;

		public static ConfigFile Config => s_config;

		public static event Action<Feature> Changed;

		public static Feature Register(string name, bool defaultOn, string description)
		{
			if (s_byName.TryGetValue(name, out var value))
			{
				return value;
			}
			Feature feature = new Feature(name, defaultOn, description);
			s_byName.Add(name, feature);
			if (s_config != null)
			{
				feature.Bind(s_config);
			}
			return feature;
		}

		public static bool Get(string name)
		{
			if (s_byName.TryGetValue(name, out var value))
			{
				return value.On;
			}
			return false;
		}

		public static bool Set(string name, bool on)
		{
			if (!s_byName.TryGetValue(name, out var value))
			{
				return false;
			}
			value.Switch(on);
			return true;
		}

		internal static void BindConfig(ConfigFile config)
		{
			s_config = config;
			foreach (Feature value in s_byName.Values)
			{
				value.Bind(config);
			}
		}

		internal static void Raise(Feature f)
		{
			Features.Changed?.Invoke(f);
		}
	}
	public sealed class Feature
	{
		public readonly string Name;

		public readonly string Description;

		public bool On;

		private ConfigEntry<bool> _entry;

		public event Action<bool> Switched;

		internal Feature(string name, bool on, string description)
		{
			Name = name;
			On = on;
			Description = description;
		}

		internal void Bind(ConfigFile config)
		{
			if (_entry == null)
			{
				_entry = config.Bind<bool>("Engine", Name, On, Description);
				Switch(_entry.Value);
				_entry.SettingChanged += delegate
				{
					Switch(_entry.Value);
				};
			}
		}

		internal void Switch(bool on)
		{
			if (_entry != null && _entry.Value != on)
			{
				_entry.Value = on;
			}
			if (On != on)
			{
				On = on;
				this.Switched?.Invoke(on);
				Features.Raise(this);
			}
		}

		public override string ToString()
		{
			return Name + "=" + (On ? "on" : "off");
		}
	}
}
namespace RealPortal.Engine
{
	[AttributeUsage(AttributeTargets.Class)]
	public sealed class EngineModuleAttribute : Attribute
	{
	}
	[BepInPlugin("valheim.realportal.engine", "Real Portal Engine", "0.1.2")]
	public class EnginePlugin : BaseUnityPlugin
	{
		public const string Guid = "valheim.realportal.engine";

		public const string Name = "Real Portal Engine";

		public const string Version = "0.1.2";

		internal static ManualLogSource Log;

		internal static Harmony Harmony;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("valheim.realportal.engine");
			foreach (Type item in from t in typeof(EnginePlugin).Assembly.GetTypes()
				where t.GetCustomAttribute<EngineModuleAttribute>() != null
				orderby t.Name
				select t)
			{
				MethodInfo method = item.GetMethod("Install", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				try
				{
					method?.Invoke(null, new object[1] { Harmony });
					Log.LogInfo((object)("module " + item.Name + " installed"));
				}
				catch (Exception ex)
				{
					Log.LogError((object)$"module {item.Name} failed to install, left out: {ex.InnerException ?? ex}");
				}
			}
			Features.BindConfig(((BaseUnityPlugin)this).Config);
			Log.LogInfo((object)("features: " + string.Join(", ", Features.All.Select((Feature f) => f.ToString()))));
		}
	}
	[EngineModule]
	public static class AiStaggerModule
	{
		private sealed class FarEntry
		{
			internal int Wait;

			internal int Owed;

			internal long Seen;
		}

		private sealed class FarByReference : IEqualityComparer<IUpdateAI>
		{
			internal static readonly FarByReference Instance = new FarByReference();

			public bool Equals(IUpdateAI a, IUpdateAI b)
			{
				return a == b;
			}

			public int GetHashCode(IUpdateAI o)
			{
				return RuntimeHelpers.GetHashCode(o);
			}
		}

		private delegate void HaveFriendsFn(BaseAI ai, float range, out Character hurtFriend, out Character friend);

		public sealed class Scheduler<T> where T : class
		{
			private sealed class Entry
			{
				internal int Phase;

				internal int PrevIndex = -1;

				internal long SeenStep = -1L;

				internal long LastSeq = -1L;

				internal long Epoch = -1L;
			}

			private sealed class ByReference : IEqualityComparer<T>
			{
				internal static readonly ByReference Instance = new ByReference();

				public bool Equals(T a, T b)
				{
					return a == b;
				}

				public int GetHashCode(T o)
				{
					return RuntimeHelpers.GetHashCode(o);
				}
			}

			public const int Phases = 5;

			private const int RingSize = 8;

			private const int LookAhead = 4;

			private const int SweepSteps = 512;

			private const byte None = 0;

			private const byte OffSource = 1;

			private const byte OnSource = 2;

			private readonly byte[] m_src = new byte[8];

			private readonly long[] m_at = new long[8];

			private readonly long[] m_seq = new long[8];

			private readonly Dictionary<T, Entry> m_entries = new Dictionary<T, Entry>(ByReference.Instance);

			private readonly int[] m_load = new int[5];

			private readonly int[] m_count = new int[5];

			private readonly List<T> m_stale = new List<T>();

			private T[] m_prev = new T[64];

			private T[] m_cur = new T[64];

			private Entry[] m_prevE = new Entry[64];

			private Entry[] m_curE = new Entry[64];

			private int m_prevCount;

			private long m_step;

			private long m_epoch;

			private long m_lastWalk;

			private long m_onSources;

			private bool m_lastOn;

			private bool m_verify;

			public Action<T, long, long, long> Mismatched;

			public long Resets;

			public long Sources;

			public long Delivered;

			public long Walks;

			public long Created;

			public long VerifyChecks;

			public long VerifyMismatches;

			public int LastPass;

			public int MaxPass;

			public bool Verify
			{
				get
				{
					return m_verify;
				}
				set
				{
					if (value && !m_verify)
					{
						m_epoch++;
					}
					m_verify = value;
				}
			}

			public long StepCount => m_step;

			public int Tracked => m_entries.Count;

			public int[] Load => (int[])m_load.Clone();

			public int PhaseOf(T item)
			{
				if (item == null || !m_entries.TryGetValue(item, out var value))
				{
					return -1;
				}
				return value.Phase;
			}

			public void Reset()
			{
				Array.Clear(m_src, 0, 8);
				Array.Clear(m_at, 0, 8);
				Array.Clear(m_seq, 0, 8);
				m_entries.Clear();
				Array.Clear(m_load, 0, 5);
				Array.Clear(m_count, 0, 5);
				m_stale.Clear();
				Array.Clear(m_prev, 0, m_prev.Length);
				Array.Clear(m_prevE, 0, m_prevE.Length);
				Array.Clear(m_cur, 0, m_cur.Length);
				Array.Clear(m_curE, 0, m_curE.Length);
				m_prevCount = 0;
				m_lastWalk = m_step;
				m_epoch++;
				LastPass = 0;
				Resets++;
			}

			public int Step(bool tick, bool on, List<T> items, List<T> subset)
			{
				long num = ++m_step;
				int num2 = (int)(num & 7);
				m_at[num2] = num;
				m_src[num2] = (byte)(tick ? ((!on) ? 1 : 2) : 0);
				if (tick)
				{
					Sources++;
					if (on)
					{
						m_seq[num2] = ++m_onSources;
					}
				}
				if (on != m_lastOn)
				{
					m_lastOn = on;
					m_epoch++;
				}
				if (num % 512 == 0L)
				{
					Sweep(num);
				}
				subset.Clear();
				int num3 = 0;
				for (int i = 0; i < 5; i++)
				{
					long num4 = num - i;
					int num5 = (int)(num4 & 7);
					if (num4 > 0 && m_at[num5] == num4 && m_src[num5] == 2)
					{
						num3 |= 1 << i;
					}
				}
				if (num3 == 0)
				{
					LastPass = 0;
					return 0;
				}
				Walk(num, num3, items, subset);
				LastPass = subset.Count;
				if (LastPass > MaxPass)
				{
					MaxPass = LastPass;
				}
				Delivered += LastPass;
				return LastPass;
			}

			private void Walk(long s, int due, List<T> items, List<T> subset)
			{
				Walks++;
				m_lastWalk = s;
				int count = items.Count;
				if (m_cur.Length < count)
				{
					int num = Math.Max(count, m_cur.Length * 2);
					m_cur = new T[num];
					m_curE = new Entry[num];
				}
				Array.Clear(m_count, 0, 5);
				int num2 = 0;
				for (int i = 0; i < count; i++)
				{
					T val = items[i];
					Entry value = null;
					if (val != null)
					{
						if (num2 < m_prevCount && m_prev[num2] == val)
						{
							value = m_prevE[num2++];
						}
						else
						{
							for (int j = num2 + 1; j < m_prevCount && j <= num2 + 4; j++)
							{
								if (m_prev[j] == val)
								{
									value = m_prevE[j];
									num2 = j + 1;
									break;
								}
							}
							if (value == null)
							{
								if (m_entries.TryGetValue(val, out value))
								{
									int prevIndex = value.PrevIndex;
									if (prevIndex >= num2 && prevIndex < m_prevCount && m_prev[prevIndex] == val)
									{
										num2 = prevIndex + 1;
									}
								}
								else
								{
									value = new Entry
									{
										Phase = Lightest()
									};
									m_load[value.Phase]++;
									m_entries.Add(val, value);
									Created++;
								}
							}
						}
					}
					int num3 = value?.Phase ?? 0;
					m_count[num3]++;
					if (Verify && value != null && value.SeenStep != s - 1 && value.SeenStep != s)
					{
						value.LastSeq = -1L;
					}
					if (((due >> num3) & 1) != 0)
					{
						subset.Add(val);
						if (Verify && value != null)
						{
							Check(value, s, num3, val);
						}
					}
					if (value != null)
					{
						value.PrevIndex = i;
						value.SeenStep = s;
					}
					m_cur[i] = val;
					m_curE[i] = value;
				}
				T[] prev = m_prev;
				m_prev = m_cur;
				m_cur = prev;
				Entry[] prevE = m_prevE;
				m_prevE = m_curE;
				m_curE = prevE;
				Array.Clear(m_cur, 0, Math.Min(m_cur.Length, m_prevCount));
				Array.Clear(m_curE, 0, Math.Min(m_curE.Length, m_prevCount));
				m_prevCount = count;
				Array.Copy(m_count, m_load, 5);
			}

			private void Check(Entry e, long s, int phase, T item)
			{
				long num = s - phase;
				long num2 = m_seq[(int)(num & 7)];
				if (e.Epoch == m_epoch && e.LastSeq >= 0)
				{
					VerifyChecks++;
					if (num2 != e.LastSeq + 1)
					{
						VerifyMismatches++;
						Mismatched?.Invoke(item, s, e.LastSeq, num2);
					}
				}
				e.LastSeq = num2;
				e.Epoch = m_epoch;
			}

			private int Lightest()
			{
				int num = 0;
				for (int i = 1; i < 5; i++)
				{
					if (m_load[i] < m_load[num])
					{
						num = i;
					}
				}
				return num;
			}

			private void Sweep(long s)
			{
				m_stale.Clear();
				foreach (KeyValuePair<T, Entry> entry in m_entries)
				{
					if (entry.Value.SeenStep < s - 512)
					{
						m_stale.Add(entry.Key);
					}
				}
				for (int i = 0; i < m_stale.Count; i++)
				{
					m_entries.Remove(m_stale[i]);
				}
				m_stale.Clear();
				if (s - m_lastWalk > 512 && m_prevCount > 0)
				{
					Array.Clear(m_prev, 0, m_prevCount);
					Array.Clear(m_prevE, 0, m_prevCount);
					m_prevCount = 0;
				}
			}
		}

		internal static readonly Feature Stagger = Features.Register("AiStagger", defaultOn: false, "Creature AI ticks (20 Hz) are spread over all fixed steps by phase instead of all AIs in two steps out of five; each AI keeps the game's tick sequence and dt.");

		internal static readonly Feature FriendSkip = Features.Register("AiFriendScanSkip", defaultOn: true, "MonsterAI skips its once-a-second scans for friends when no item in the humanoid's inventory targets friends (the results would not be read).");

		internal static readonly Feature Verify = Features.Register("AiVerify", defaultOn: false, "Lab: checks that every AI receives every AI tick exactly once under AiStagger, and runs the friend scans anyway while counting the skips AiFriendScanSkip would make.");

		private const float Tick = 0.05f;

		private const string Scope = "MonoUpdaters.FixedUpdate.BaseAI";

		private const string LabOwners = "valheim.realportal.lab";

		private const float ForeignCheckSeconds = 10f;

		public static long Passes;

		public static int MaxGamePass;

		public static long FriendScansRun;

		public static long FriendScansSkipped;

		public static long FriendWouldSkip;

		public static long FarTicks;

		public static long FarSkipped;

		public static long FarThinks;

		public static long FarFlushes;

		public static long FarPasses;

		public static long FarDropped;

		public static long FarHookErrors;

		public static Func<BaseAI, bool> IsFarSlow;

		public static int FarEvery = 4;

		private static readonly Scheduler<IUpdateAI> s_sched = new Scheduler<IUpdateAI>();

		private static readonly List<IUpdateAI> s_subset = new List<IUpdateAI>();

		private static FieldRef<MonoUpdaters, float> s_timer;

		private static FieldRef<MonoUpdaters, List<IUpdateAI>> s_container;

		private static MethodInfo s_fixedUpdate;

		private static MethodInfo s_updateAI;

		private static bool s_staggerPatched;

		private static bool s_staggerForeign;

		private static bool s_lastOn;

		private static bool s_broken;

		private static float s_nextStaggerCheck;

		private static MonoUpdaters s_owner;

		private static float s_probe;

		private const int MaxFarEvery = 8;

		private const long FarSweepSteps = 256L;

		private const float FarHookRetrySeconds = 10f;

		private static readonly Dictionary<IUpdateAI, FarEntry> s_far = new Dictionary<IUpdateAI, FarEntry>(FarByReference.Instance);

		private static readonly Stack<FarEntry> s_farPool = new Stack<FarEntry>();

		private static readonly List<IUpdateAI> s_farStale = new List<IUpdateAI>();

		private static readonly List<IUpdateAI>[] s_owed = NewGroups();

		private static Func<BaseAI, bool> s_farHook;

		private static bool s_farPath;

		private static bool s_farOn;

		private static int s_farNext;

		private static long s_farSweptAt;

		private static Delegate s_farBroken;

		private static float s_farBrokenAt;

		private static FieldRef<Humanoid, Inventory> s_inventory;

		private static MethodBase[] s_friendWatch;

		private static MethodInfo s_selectBestAttack;

		private static bool s_friendPatched;

		private static bool s_friendForeign;

		private static float s_nextFriendCheck;

		private static readonly FieldInfo s_timerField = AccessTools.Field(typeof(MonoUpdaters), "m_updateAITimer");

		private static readonly FieldInfo s_aiField = AccessTools.Field(typeof(MonoUpdaters), "m_ai");

		private static readonly MethodInfo s_instancesGetter = AccessTools.PropertyGetter(typeof(BaseAI), "Instances");

		private static readonly MethodInfo s_aiStep = AccessTools.DeclaredMethod(typeof(AiStaggerModule), "AiStep", (Type[])null, (Type[])null);

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

		private static readonly FieldInfo s_labels = AccessTools.Field(typeof(CodeInstruction), "labels");

		private static readonly FieldInfo s_blocks = AccessTools.Field(typeof(CodeInstruction), "blocks");

		private static HaveFriendsFn s_haveFriends;

		private static readonly MethodInfo s_haveFriendsCall = AccessTools.DeclaredMethod(typeof(BaseAI), "HaveFriendsInRange", new Type[3]
		{
			typeof(float),
			typeof(Character).MakeByRefType(),
			typeof(Character).MakeByRefType()
		}, (Type[])null);

		private static readonly MethodInfo s_friendScan = AccessTools.DeclaredMethod(typeof(AiStaggerModule), "FriendScan", (Type[])null, (Type[])null);

		public static bool StaggerPatched => s_staggerPatched;

		public static bool StaggerForeign => s_staggerForeign;

		public static bool StaggerActive => s_lastOn;

		public static long Steps => s_sched.StepCount;

		public static long SourceTicks => s_sched.Sources;

		public static long Deliveries => s_sched.Delivered;

		public static int LastPass => s_sched.LastPass;

		public static int MaxPass => s_sched.MaxPass;

		public static long VerifyChecks => s_sched.VerifyChecks;

		public static long VerifyMismatches => s_sched.VerifyMismatches;

		public static long SchedulerResets => s_sched.Resets;

		public static bool FriendPatched => s_friendPatched;

		public static bool FriendForeign => s_friendForeign;

		public static bool FarActive => s_farOn;

		public static int FarTracked => s_far.Count;

		public static void ResetPeaks()
		{
			s_sched.MaxPass = 0;
			MaxGamePass = 0;
		}

		public static string Describe()
		{
			return $"AiStagger: patched {s_staggerPatched}, active {s_lastOn}, foreign {s_staggerForeign}, steps {s_sched.StepCount}, source ticks {s_sched.Sources}, " + string.Format("deliveries {0}, pass last/max {1}/{2} (game max {3}), phase load [{4}], ", s_sched.Delivered, s_sched.LastPass, s_sched.MaxPass, MaxGamePass, string.Join(",", s_sched.Load)) + $"verify {s_sched.VerifyChecks}/{s_sched.VerifyMismatches} mismatches, sessions {s_sched.Resets}; " + string.Format("far AIs: hook {0}, active {1}, every {2}, tracked {3}, ticks {4}, ", (IsFarSlow != null) ? "set" : "unset", s_farOn, FarEvery, s_far.Count, FarTicks) + $"skipped {FarSkipped}, thinks {FarThinks}, flushed {FarFlushes}, passes {FarPasses}, dropped {FarDropped}, hook errors {FarHookErrors}; " + $"AiFriendScanSkip: patched {s_friendPatched}, foreign {s_friendForeign}, run {FriendScansRun}, skipped {FriendScansSkipped}, would skip {FriendWouldSkip}";
		}

		private static void Install(Harmony harmony)
		{
			try
			{
				InstallStagger(harmony);
			}
			catch (Exception ex)
			{
				s_staggerPatched = false;
				EnginePlugin.Log.LogError((object)("AiStagger: not installed, AI ticks stay as in the game: " + ex));
			}
			try
			{
				InstallFriendSkip(harmony);
			}
			catch (Exception ex2)
			{
				s_friendPatched = false;
				EnginePlugin.Log.LogError((object)("AiFriendScanSkip: not installed, friend scans stay as in the game: " + ex2));
			}
			Stagger.Switched += delegate
			{
				s_nextStaggerCheck = 0f;
			};
			FriendSkip.Switched += delegate
			{
				s_nextFriendCheck = 0f;
			};
			Verify.Switched += delegate(bool on)
			{
				s_sched.Verify = on;
			};
			s_sched.Verify = Verify.On;
		}

		private static void InstallStagger(Harmony harmony)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			s_timer = AccessTools.FieldRefAccess<MonoUpdaters, float>("m_updateAITimer");
			s_container = AccessTools.FieldRefAccess<MonoUpdaters, List<IUpdateAI>>("m_ai");
			s_fixedUpdate = AccessTools.DeclaredMethod(typeof(MonoUpdaters), "FixedUpdate", (Type[])null, (Type[])null);
			s_updateAI = AccessTools.DeclaredMethod(typeof(MonoUpdatersExtra), "UpdateAI", (Type[])null, (Type[])null);
			if (s_fixedUpdate == null || s_updateAI == null)
			{
				EnginePlugin.Log.LogWarning((object)"AiStagger: MonoUpdaters.FixedUpdate or MonoUpdatersExtra.UpdateAI not found (game update?), left as in the game.");
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(MonoUpdaters), "OnDestroy", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(AiStaggerModule), "UpdatersDestroyed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				EnginePlugin.Log.LogWarning((object)("AiStagger: MonoUpdaters.OnDestroy not patched (the next session still starts afresh): " + ex.Message));
			}
			harmony.Patch((MethodBase)s_fixedUpdate, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(AiStaggerModule), "FixedUpdateIL", (Type[])null)
			{
				priority = 0
			}, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void UpdatersDestroyed(MonoUpdaters __instance)
		{
			if (__instance == s_owner)
			{
				s_owner = null;
				s_sched.Reset();
				s_subset.Clear();
				ResetFar();
			}
		}

		private static IEnumerable<CodeInstruction> FixedUpdateIL(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int num = -1;
			int num2 = 0;
			object obj = null;
			for (int i = 0; i + 22 < list.Count; i++)
			{
				if (IsTimerBlock(list, i, out var end))
				{
					num2++;
					num = i;
					obj = end;
				}
			}
			if (num2 != 1)
			{
				s_staggerPatched = false;
				ReportOnce("stagger", $"AiStagger: the AI timer block of MonoUpdaters.FixedUpdate was found {num2} times (changed by another mod or an update?), left as in the game.", warning: true);
				return list;
			}
			CodeInstruction[] array = (CodeInstruction[])(object)new CodeInstruction[4]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(list[num + 3].opcode, list[num + 3].operand),
				new CodeInstruction(OpCodes.Call, (object)s_aiStep),
				new CodeInstruction(OpCodes.Brtrue, obj)
			};
			MoveMarks(s_labels, list[num], array[0]);
			MoveMarks(s_blocks, list[num], array[0]);
			list.InsertRange(num, array);
			s_staggerPatched = true;
			ReportOnce("stagger", "AiStagger: MonoUpdaters.FixedUpdate AI timer block wrapped.", warning: false);
			return list;
		}

		private static bool IsTimerBlock(List<CodeInstruction> c, int i, out object end)
		{
			end = null;
			if (!Is(c[i], OpCodes.Ldarg_0) || !Is(c[i + 1], OpCodes.Ldarg_0) || !LoadsField(c[i + 2], s_timerField) || !IsLocalOrArgLoad(c[i + 3]) || !Is(c[i + 4], OpCodes.Add) || !StoresField(c[i + 5], s_timerField) || !Is(c[i + 6], OpCodes.Ldarg_0) || !LoadsField(c[i + 7], s_timerField) || !IsR4(c[i + 8], 0.05f) || (!Is(c[i + 9], OpCodes.Blt_Un) && !Is(c[i + 9], OpCodes.Blt_Un_S)) || c[i + 9].operand == null || !Is(c[i + 10], OpCodes.Ldarg_0) || !LoadsField(c[i + 11], s_aiField) || !Calls(c[i + 12], s_instancesGetter) || !Is(c[i + 13], OpCodes.Ldstr) || !IsR4(c[i + 14], 0.05f) || !Calls(c[i + 15], s_updateAI) || !Is(c[i + 16], OpCodes.Ldarg_0) || !Is(c[i + 17], OpCodes.Ldarg_0) || !LoadsField(c[i + 18], s_timerField) || !IsR4(c[i + 19], 0.05f) || !Is(c[i + 20], OpCodes.Sub) || !StoresField(c[i + 21], s_timerField))
			{
				return false;
			}
			object operand = c[i + 9].operand;
			if (!(s_labels?.GetValue(c[i + 22]) is IList list) || !list.Contains(operand))
			{
				return false;
			}
			for (int j = i + 1; j <= i + 21; j++)
			{
				if (!Plain(c[j]))
				{
					return false;
				}
			}
			end = operand;
			return true;
		}

		private static bool Plain(CodeInstruction ci)
		{
			if (!(s_labels?.GetValue(ci) is ICollection { Count: not 0 }))
			{
				if (s_blocks?.GetValue(ci) is ICollection collection2)
				{
					return collection2.Count == 0;
				}
				return true;
			}
			return false;
		}

		private static void MoveMarks(FieldInfo field, CodeInstruction from, CodeInstruction to)
		{
			if (!(field?.GetValue(from) is IList list) || !(field.GetValue(to) is IList list2))
			{
				return;
			}
			foreach (object item in list)
			{
				list2.Add(item);
			}
			list.Clear();
		}

		private static bool Is(CodeInstruction ci, OpCode op)
		{
			return ci.opcode == op;
		}

		private static bool LoadsField(CodeInstruction ci, FieldInfo f)
		{
			if (f != null && ci.opcode == OpCodes.Ldfld)
			{
				return object.Equals(ci.operand, f);
			}
			return false;
		}

		private static bool StoresField(CodeInstruction ci, FieldInfo f)
		{
			if (f != null && ci.opcode == OpCodes.Stfld)
			{
				return object.Equals(ci.operand, f);
			}
			return false;
		}

		private static bool Calls(CodeInstruction ci, MethodInfo m)
		{
			if (m != null && (ci.opcode == OpCodes.Call || ci.opcode == OpCodes.Callvirt))
			{
				return object.Equals(ci.operand, m);
			}
			return false;
		}

		private static bool IsR4(CodeInstruction ci, float v)
		{
			if (ci.opcode == OpCodes.Ldc_R4 && ci.operand is float num)
			{
				return num.Equals(v);
			}
			return false;
		}

		private static bool IsLocalOrArgLoad(CodeInstruction ci)
		{
			if (!(ci.opcode == OpCodes.Ldloc_0) && !(ci.opcode == OpCodes.Ldloc_1) && !(ci.opcode == OpCodes.Ldloc_2) && !(ci.opcode == OpCodes.Ldloc_3) && !(ci.opcode == OpCodes.Ldloc_S))
			{
				return ci.opcode == OpCodes.Ldloc;
			}
			return true;
		}

		private static bool AiStep(MonoUpdaters updaters, float fixedDeltaTime)
		{
			if (s_broken)
			{
				return false;
			}
			if (updaters != s_owner)
			{
				if ((Object)(object)s_owner != (Object)null)
				{
					return false;
				}
				s_owner = updaters;
				s_sched.Reset();
				s_subset.Clear();
				ResetFar();
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= s_nextStaggerCheck)
			{
				CheckStaggerForeign(unscaledTime);
			}
			bool flag = Stagger.On && !s_staggerForeign;
			if (flag != s_lastOn)
			{
				s_lastOn = flag;
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)(flag ? "AiStagger: AI ticks staggered by phase." : "AiStagger: AI ticks as in the game."));
				}
			}
			FarStep(unscaledTime);
			ref float reference = ref s_timer.Invoke(updaters);
			s_probe = reference + fixedDeltaTime;
			bool flag2 = s_probe >= 0.05f;
			List<IUpdateAI> instances = BaseAI.Instances;
			if (flag2 && instances.Count > MaxGamePass)
			{
				MaxGamePass = instances.Count;
			}
			int num;
			try
			{
				num = s_sched.Step(flag2, flag, instances, s_subset);
			}
			catch (Exception ex)
			{
				s_broken = true;
				s_lastOn = false;
				s_subset.Clear();
				ResetFar();
				s_farOn = false;
				ManualLogSource log2 = EnginePlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("AiStagger: scheduler failed, AI ticks as in the game for the rest of the session: " + ex));
				}
				return false;
			}
			if (!flag)
			{
				if (num > 0)
				{
					Pass(updaters);
				}
				if (!s_farPath)
				{
					return false;
				}
				reference = s_probe;
				if (flag2)
				{
					s_subset.AddRange(instances);
					Pass(updaters);
					reference -= 0.05f;
				}
				return true;
			}
			reference = s_probe;
			if (num > 0)
			{
				Pass(updaters);
			}
			if (flag2)
			{
				reference -= 0.05f;
			}
			return true;
		}

		private static void Pass(MonoUpdaters updaters)
		{
			Passes++;
			List<IUpdateAI> list = s_container.Invoke(updaters);
			if (!s_farPath)
			{
				MonoUpdatersExtra.UpdateAI(list, s_subset, "MonoUpdaters.FixedUpdate.BaseAI", 0.05f);
				s_subset.Clear();
				return;
			}
			Split();
			MonoUpdatersExtra.UpdateAI(list, s_owed[1], "MonoUpdaters.FixedUpdate.BaseAI", 0.05f);
			s_owed[1].Clear();
			for (int i = 2; i <= 8; i++)
			{
				List<IUpdateAI> list2 = s_owed[i];
				if (list2.Count != 0)
				{
					FarPasses++;
					MonoUpdatersExtra.UpdateAI(list, list2, "MonoUpdaters.FixedUpdate.BaseAI", (float)i * 0.05f);
					list2.Clear();
				}
			}
		}

		private static void FarStep(float now)
		{
			Func<BaseAI, bool> func = IsFarSlow;
			if (func != null && (object)func == s_farBroken && now - s_farBrokenAt < 10f)
			{
				func = null;
			}
			if (s_staggerForeign)
			{
				func = null;
				if (s_far.Count > 0)
				{
					ResetFar();
				}
			}
			s_farHook = func;
			s_farPath = func != null || s_far.Count > 0;
			if (func != null != s_farOn)
			{
				s_farOn = func != null;
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)(s_farOn ? $"AiStagger: far AIs (Real Portal) think every {FarEvery} ticks." : "AiStagger: far AIs think every tick."));
				}
			}
			if (s_far.Count > 0 && s_sched.StepCount - s_farSweptAt >= 256)
			{
				SweepFar();
			}
		}

		private static void Split()
		{
			for (int i = 1; i <= 8; i++)
			{
				s_owed[i].Clear();
			}
			Func<BaseAI, bool> hook = s_farHook;
			int num = ((FarEvery < 1) ? 1 : ((FarEvery > 8) ? 8 : FarEvery));
			long stepCount = s_sched.StepCount;
			List<IUpdateAI> list = s_subset;
			for (int j = 0; j < list.Count; j++)
			{
				IUpdateAI val = list[j];
				int num2 = 1;
				if (hook != null)
				{
					BaseAI val2 = (BaseAI)(object)((val is BaseAI) ? val : null);
					if (val2 != null && AskFar(ref hook, val2))
					{
						FarTicks++;
						if (!s_far.TryGetValue(val, out var value))
						{
							value = ((s_farPool.Count > 0) ? s_farPool.Pop() : new FarEntry());
							s_farNext = (s_farNext + 1) % num;
							value.Wait = s_farNext + 1;
							value.Owed = 0;
							s_far.Add(val, value);
						}
						value.Seen = stepCount;
						value.Owed++;
						if (--value.Wait > 0)
						{
							FarSkipped++;
							continue;
						}
						value.Wait = num;
						num2 = value.Owed;
						value.Owed = 0;
						FarThinks++;
						goto IL_01b3;
					}
				}
				if (s_far.Count > 0 && val != null && s_far.TryGetValue(val, out var value2))
				{
					num2 = value2.Owed + 1;
					s_far.Remove(val);
					s_farPool.Push(value2);
					FarFlushes++;
				}
				goto IL_01b3;
				IL_01b3:
				s_owed[(num2 < 1) ? 1 : ((num2 > 8) ? 8 : num2)].Add(val);
			}
			list.Clear();
		}

		private static bool AskFar(ref Func<BaseAI, bool> hook, BaseAI ai)
		{
			try
			{
				return hook(ai);
			}
			catch (Exception arg)
			{
				FarHookErrors++;
				if ((object)s_farBroken != hook)
				{
					ManualLogSource log = EnginePlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)$"AiStagger: Real Portal's IsFarSlow threw, far AIs think every tick until it is replaced (asked again every {10f:F0} s): {arg}");
					}
				}
				s_farBroken = hook;
				s_farBrokenAt = Time.unscaledTime;
				hook = null;
				s_farHook = null;
				return false;
			}
		}

		private static void SweepFar()
		{
			long num = (s_farSweptAt = s_sched.StepCount);
			s_farStale.Clear();
			foreach (KeyValuePair<IUpdateAI, FarEntry> item in s_far)
			{
				if (num - item.Value.Seen > 256)
				{
					s_farStale.Add(item.Key);
				}
			}
			for (int i = 0; i < s_farStale.Count; i++)
			{
				FarEntry farEntry = s_far[s_farStale[i]];
				FarDropped += farEntry.Owed;
				s_far.Remove(s_farStale[i]);
				s_farPool.Push(farEntry);
			}
			s_farStale.Clear();
		}

		private static void ResetFar()
		{
			foreach (KeyValuePair<IUpdateAI, FarEntry> item in s_far)
			{
				FarDropped += item.Value.Owed;
				s_farPool.Push(item.Value);
			}
			s_far.Clear();
			for (int i = 1; i <= 8; i++)
			{
				s_owed[i].Clear();
			}
			s_farStale.Clear();
		}

		private static List<IUpdateAI>[] NewGroups()
		{
			List<IUpdateAI>[] array = new List<IUpdateAI>[9];
			for (int i = 1; i <= 8; i++)
			{
				array[i] = new List<IUpdateAI>();
			}
			return array;
		}

		private static void CheckStaggerForeign(float now)
		{
			s_nextStaggerCheck = now + 10f;
			string text = "";
			bool flag;
			try
			{
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)s_fixedUpdate);
				Patches patchInfo2 = Harmony.GetPatchInfo((MethodBase)s_updateAI);
				flag = (patchInfo != null && (Foreign(patchInfo.Transpilers) || Foreign(patchInfo.ILManipulators))) || (patchInfo2 != null && (Foreign(patchInfo2.Prefixes) || Foreign(patchInfo2.Postfixes) || Foreign(patchInfo2.Transpilers) || Foreign(patchInfo2.Finalizers) || Foreign(patchInfo2.ILManipulators)));
				if (flag)
				{
					text = "another mod patches MonoUpdaters.FixedUpdate (IL) or MonoUpdatersExtra.UpdateAI";
				}
			}
			catch (Exception ex)
			{
				flag = true;
				text = "reading Harmony patch info failed (" + ex.Message + ")";
			}
			if (flag != s_staggerForeign)
			{
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)(flag ? ("AiStagger: " + text + ", AI ticks as in the game.") : "AiStagger: no foreign patches any more."));
				}
			}
			s_staggerForeign = flag;
		}

		private static void InstallFriendSkip(Harmony harmony)
		{
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(BaseAI), "HaveFriendsInRange", new Type[3]
			{
				typeof(float),
				typeof(Character).MakeByRefType(),
				typeof(Character).MakeByRefType()
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(BaseAI), "HaveFriendInRange", new Type[2]
			{
				typeof(List<Character>),
				typeof(float)
			}, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(BaseAI), "HaveHurtFriendInRange", new Type[2]
			{
				typeof(List<Character>),
				typeof(float)
			}, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.DeclaredMethod(typeof(Humanoid), "EquipBestWeapon", (Type[])null, (Type[])null);
			s_selectBestAttack = AccessTools.DeclaredMethod(typeof(MonsterAI), "SelectBestAttack", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null || s_selectBestAttack == null)
			{
				EnginePlugin.Log.LogWarning((object)"AiFriendScanSkip: a target method is missing (game update?), left as in the game.");
				return;
			}
			ParameterInfo[] parameters = s_selectBestAttack.GetParameters();
			if (parameters.Length < 1 || parameters[0].ParameterType != typeof(Humanoid))
			{
				EnginePlugin.Log.LogWarning((object)"AiFriendScanSkip: MonsterAI.SelectBestAttack has another signature (game update?), left as in the game.");
				return;
			}
			s_inventory = AccessTools.FieldRefAccess<Humanoid, Inventory>("m_inventory");
			s_haveFriends = AccessTools.MethodDelegate<HaveFriendsFn>(methodInfo, (object)null, true);
			s_friendWatch = new MethodBase[4] { methodInfo, methodInfo2, methodInfo3, methodInfo4 };
			harmony.Patch((MethodBase)s_selectBestAttack, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(AiStaggerModule), "SelectBestAttackIL", (Type[])null)
			{
				priority = 0
			}, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static IEnumerable<CodeInstruction> SelectBestAttackIL(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = -1;
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (Calls(list[i], s_haveFriendsCall))
				{
					num++;
					index = i;
				}
			}
			if (num != 1 || !Plain(list[index]))
			{
				s_friendPatched = false;
				ReportOnce("friend", $"AiFriendScanSkip: MonsterAI.SelectBestAttack calls HaveFriendsInRange {num} times or jumps onto the call (changed by another mod or an update?), left as in the game.", warning: true);
				return list;
			}
			list[index].opcode = OpCodes.Call;
			list[index].operand = s_friendScan;
			list.Insert(index, new CodeInstruction(OpCodes.Ldarg_1, (object)null));
			s_friendPatched = true;
			ReportOnce("friend", "AiFriendScanSkip: MonsterAI.SelectBestAttack friend scan routed.", warning: false);
			return list;
		}

		private static void FriendScan(BaseAI ai, float range, out Character hurtFriend, out Character friend, Humanoid humanoid)
		{
			if (FriendSkip.On && (Object)(object)humanoid != (Object)null)
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime >= s_nextFriendCheck)
				{
					CheckFriendForeign(unscaledTime);
				}
				if (!s_friendForeign && !NeedsFriends(humanoid))
				{
					if (!Verify.On)
					{
						FriendScansSkipped++;
						hurtFriend = null;
						friend = null;
						return;
					}
					FriendWouldSkip++;
				}
			}
			FriendScansRun++;
			s_haveFriends(ai, range, out hurtFriend, out friend);
		}

		private static bool NeedsFriends(Humanoid humanoid)
		{
			try
			{
				return ItemTargetsFriends(humanoid);
			}
			catch (Exception)
			{
				return true;
			}
		}

		private static bool ItemTargetsFriends(Humanoid humanoid)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			Inventory val = s_inventory.Invoke(humanoid);
			if (val == null)
			{
				return true;
			}
			List<ItemData> allItems = val.GetAllItems();
			if (allItems == null)
			{
				return true;
			}
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val2 = allItems[i];
				if (val2?.m_shared == null)
				{
					return true;
				}
				AiTarget aiTargetType = val2.m_shared.m_aiTargetType;
				if ((int)aiTargetType == 2 || (int)aiTargetType == 1)
				{
					return true;
				}
			}
			return false;
		}

		private static void CheckFriendForeign(float now)
		{
			s_nextFriendCheck = now + 10f;
			bool flag = false;
			try
			{
				MethodBase[] array = s_friendWatch;
				for (int i = 0; i < array.Length; i++)
				{
					Patches patchInfo = Harmony.GetPatchInfo(array[i]);
					if (patchInfo != null && (Foreign(patchInfo.Prefixes) || Foreign(patchInfo.Postfixes) || Foreign(patchInfo.Transpilers) || Foreign(patchInfo.Finalizers) || Foreign(patchInfo.ILManipulators)))
					{
						flag = true;
					}
				}
				Patches patchInfo2 = Harmony.GetPatchInfo((MethodBase)s_selectBestAttack);
				if (patchInfo2 != null && (Foreign(patchInfo2.Transpilers) || Foreign(patchInfo2.ILManipulators)))
				{
					flag = true;
				}
			}
			catch (Exception)
			{
				flag = true;
			}
			if (flag != s_friendForeign)
			{
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)(flag ? "AiFriendScanSkip: another mod patches the friend scans, EquipBestWeapon or SelectBestAttack; scans run as in the game." : "AiFriendScanSkip: no foreign patches any more."));
				}
			}
			s_friendForeign = flag;
		}

		private static bool Foreign(IEnumerable<Patch> patches)
		{
			if (patches == null)
			{
				return false;
			}
			foreach (Patch patch in patches)
			{
				if (patch.owner != "valheim.realportal.engine" && (patch.owner == null || !patch.owner.StartsWith("valheim.realportal.lab", StringComparison.Ordinal)))
				{
					return true;
				}
			}
			return false;
		}

		private static void ReportOnce(string key, string message, bool warning)
		{
			if (s_reported.TryGetValue(key, out var value) && value == message)
			{
				return;
			}
			s_reported[key] = message;
			if (warning)
			{
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)message);
				}
			}
			else
			{
				ManualLogSource log2 = EnginePlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)message);
				}
			}
		}
	}
	[EngineModule]
	internal static class AllocFixesModule
	{
		private sealed class IndexedKeys
		{
			private const int Max = 256;

			internal readonly string Prefix;

			private string[] _keys = new string[8];

			internal IndexedKeys(string prefix)
			{
				Prefix = prefix;
			}

			internal string Get(int index)
			{
				if ((uint)index >= 256u)
				{
					return Prefix + index;
				}
				if (index >= _keys.Length)
				{
					Array.Resize(ref _keys, Math.Min(256, Math.Max(index + 1, _keys.Length * 2)));
				}
				return _keys[index] ?? (_keys[index] = Prefix + index);
			}
		}

		private sealed class ColliderPool
		{
			private const int Kept = 128;

			private const int MaxBuffer = 2048;

			private readonly string _site;

			private Collider[] _buffer = (Collider[])(object)new Collider[128];

			private readonly Collider[][] _exact = new Collider[128][];

			private Collider[] _handedOut;

			internal ColliderPool(string site)
			{
				_site = site;
			}

			internal Collider[] OverlapSphere(Vector3 position, float radius, int layerMask, QueryTriggerInteraction triggers)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: 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_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				if (!s_overlap.On)
				{
					return Physics.OverlapSphere(position, radius, layerMask, triggers);
				}
				if (_handedOut != null)
				{
					Array.Clear(_handedOut, 0, _handedOut.Length);
					_handedOut = null;
				}
				int num = Physics.OverlapSphereNonAlloc(position, radius, _buffer, layerMask, triggers);
				if (num >= _buffer.Length)
				{
					Collider[] array = Physics.OverlapSphere(position, radius, layerMask, triggers);
					Grow(array.Length);
					return array;
				}
				Collider[] array2;
				if (num == 0)
				{
					array2 = Array.Empty<Collider>();
				}
				else if (num < 128)
				{
					Collider[] obj = _exact[num] ?? (_exact[num] = (Collider[])(object)new Collider[num]);
					Collider[] array3 = obj;
					_handedOut = obj;
					array2 = array3;
				}
				else
				{
					array2 = (Collider[])(object)new Collider[num];
				}
				Array.Copy(_buffer, array2, num);
				Array.Clear(_buffer, 0, num);
				if (s_verify.On)
				{
					return Verify(array2, Physics.OverlapSphere(position, radius, layerMask, triggers));
				}
				return array2;
			}

			private void Grow(int count)
			{
				int num = _buffer.Length;
				while (num <= count && num < 2048)
				{
					num *= 2;
				}
				if (num > _buffer.Length)
				{
					_buffer = (Collider[])(object)new Collider[Math.Min(num, 2048)];
				}
				else
				{
					Array.Clear(_buffer, 0, _buffer.Length);
				}
			}

			private Collider[] Verify(Collider[] ours, Collider[] game)
			{
				VerifyChecks++;
				bool flag = ours.Length == game.Length;
				int num = 0;
				while (flag && num < ours.Length)
				{
					flag = ours[num] == game[num];
					num++;
				}
				if (flag)
				{
					return ours;
				}
				bool flag2 = ours.Length == game.Length && new HashSet<Object>((IEnumerable<Object>)(object)ours, ByReference.Instance).SetEquals((IEnumerable<Object>)(object)game);
				Mismatch(_site, flag2 ? $"the same {ours.Length} colliders in another order" : $"{ours.Length} vs {game.Length} colliders, not the same ones");
				return game;
			}
		}

		private delegate int RaycastIntoFn(PhysicsScene scene, Ray ray, RaycastHit[] hits, float maxDistance, int mask, QueryTriggerInteraction triggers);

		private delegate int SphereCastIntoFn(PhysicsScene scene, Vector3 origin, float radius, Vector3 direction, RaycastHit[] hits, float maxDistance, int mask, QueryTriggerInteraction triggers);

		private sealed class HitPool
		{
			private const int Kept = 64;

			private const int MaxBuffer = 1024;

			private const float Tolerance = 1E-06f;

			private static readonly Comparison<RaycastHit> s_byDistance = (RaycastHit x, RaycastHit y) => ((RaycastHit)(ref x)).distance.CompareTo(((RaycastHit)(ref y)).distance);

			private readonly string _site;

			internal RaycastHit[] Buffer = (RaycastHit[])(object)new RaycastHit[64];

			private readonly RaycastHit[][] _exact = new RaycastHit[64][];

			internal HitPool(string site)
			{
				_site = site;
			}

			internal RaycastHit[] Take(int n)
			{
				if (n == 0)
				{
					return Array.Empty<RaycastHit>();
				}
				RaycastHit[] array = (RaycastHit[])((n < 64) ? ((Array)(_exact[n] ?? (_exact[n] = (RaycastHit[])(object)new RaycastHit[n]))) : ((Array)new RaycastHit[n]));
				Array.Copy(Buffer, array, n);
				return array;
			}

			internal void Grow(int count)
			{
				int num = Buffer.Length;
				while (num <= count && num < 1024)
				{
					num *= 2;
				}
				if (num > Buffer.Length)
				{
					Buffer = (RaycastHit[])(object)new RaycastHit[Math.Min(num, 1024)];
				}
			}

			internal RaycastHit[] Verify(RaycastHit[] ours, RaycastHit[] game)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0209: Unknown result type (might be due to invalid IL or missing references)
				//IL_021a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0226: Unknown result type (might be due to invalid IL or missing references)
				//IL_0248: Unknown result type (might be due to invalid IL or missing references)
				//IL_0254: Unknown result type (might be due to invalid IL or missing references)
				//IL_0265: Unknown result type (might be due to invalid IL or missing references)
				//IL_0271: Unknown result type (might be due to invalid IL or missing references)
				//IL_0282: Unknown result type (might be due to invalid IL or missing references)
				//IL_028e: Unknown result type (might be due to invalid IL or missing references)
				VerifyChecks++;
				bool flag = ours.Length == game.Length;
				int num;
				for (int i = 0; flag && i < ours.Length; flag = (byte)num != 0, i++)
				{
					RaycastHit val = ours[i];
					RaycastHit val2 = game[i];
					if (((RaycastHit)(ref val)).colliderInstanceID == ((RaycastHit)(ref val2)).colliderInstanceID && ((RaycastHit)(ref val)).distance.Equals(((RaycastHit)(ref val2)).distance))
					{
						Vector3 val3 = ((RaycastHit)(ref val)).point;
						if (((Vector3)(ref val3)).Equals(((RaycastHit)(ref val2)).point))
						{
							val3 = ((RaycastHit)(ref val)).normal;
							if (((Vector3)(ref val3)).Equals(((RaycastHit)(ref val2)).normal))
							{
								num = ((((RaycastHit)(ref val)).triangleIndex == ((RaycastHit)(ref val2)).triangleIndex) ? 1 : 0);
								continue;
							}
						}
					}
					num = 0;
				}
				if (flag)
				{
					return ours;
				}
				if (!SameColliders(ours, game))
				{
					Mismatch(_site, $"{ours.Length} vs {game.Length} hits, not the same colliders");
					return game;
				}
				RaycastHit[] array = (RaycastHit[])ours.Clone();
				RaycastHit[] array2 = (RaycastHit[])game.Clone();
				Array.Sort(array, s_byDistance);
				Array.Sort(array2, s_byDistance);
				float num2 = 0f;
				for (int j = 0; j < array.Length; j++)
				{
					RaycastHit val4 = array[j];
					RaycastHit val5 = array2[j];
					if (((RaycastHit)(ref val4)).colliderInstanceID != ((RaycastHit)(ref val5)).colliderInstanceID)
					{
						Mismatch(_site, $"the same {ours.Length} colliders, another order after the game's distance sort (hit {j})");
						return game;
					}
					if (((RaycastHit)(ref val4)).distance == 0f != (((RaycastHit)(ref val5)).distance == 0f))
					{
						Mismatch(_site, $"hit {j} starts inside the collider in one answer only (distance {((RaycastHit)(ref val4)).distance} vs {((RaycastHit)(ref val5)).distance})");
						return game;
					}
					num2 = Math.Max(num2, Off(((RaycastHit)(ref val4)).distance, ((RaycastHit)(ref val5)).distance));
					num2 = Math.Max(num2, Math.Max(Off(((RaycastHit)(ref val4)).point.x, ((RaycastHit)(ref val5)).point.x), Math.Max(Off(((RaycastHit)(ref val4)).point.y, ((RaycastHit)(ref val5)).point.y), Off(((RaycastHit)(ref val4)).point.z, ((RaycastHit)(ref val5)).point.z))));
					num2 = Math.Max(num2, Math.Max(Off(((RaycastHit)(ref val4)).normal.x, ((RaycastHit)(ref val5)).normal.x), Math.Max(Off(((RaycastHit)(ref val4)).normal.y, ((RaycastHit)(ref val5)).normal.y), Off(((RaycastHit)(ref val4)).normal.z, ((RaycastHit)(ref val5)).normal.z))));
				}
				if (num2 > 1f)
				{
					Drift(_site, $"{ours.Length} hits, values off by up to {num2:0.#}x the rounding band");
				}
				else
				{
					Noise(_site, $"{ours.Length} hits: native order or rounding-level values only");
				}
				return game;
			}

			private static float Off(float a, float b)
			{
				float num = 1E-06f * Math.Max(1f, Math.Max(Math.Abs(a), Math.Abs(b)));
				return Math.Abs(a - b) / num;
			}

			private static bool SameColliders(RaycastHit[] a, RaycastHit[] b)
			{
				if (a.Length != b.Length)
				{
					return false;
				}
				int[] array = new int[a.Length];
				int[] array2 = new int[b.Length];
				for (int i = 0; i < a.Length; i++)
				{
					array[i] = ((RaycastHit)(ref a[i])).colliderInstanceID;
					array2[i] = ((RaycastHit)(ref b[i])).colliderInstanceID;
				}
				Array.Sort(array);
				Array.Sort(array2);
				for (int j = 0; j < array.Length; j++)
				{
					if (array[j] != array2[j])
					{
						return false;
					}
				}
				return true;
			}
		}

		private readonly struct SpawnKey : IEquatable<SpawnKey>
		{
			private readonly string _salt;

			private readonly GameObject _prefab;

			private readonly int _index;

			internal SpawnKey(string salt, GameObject prefab, int index)
			{
				_salt = salt;
				_prefab = prefab;
				_index = index;
			}

			public bool Equals(SpawnKey other)
			{
				if (_prefab == other._prefab && _index == other._index)
				{
					return string.Equals(_salt, other._salt);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is SpawnKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (((RuntimeHelpers.GetHashCode(_prefab) * 397) ^ _index) * 397) ^ (_salt?.GetHashCode() ?? 0);
			}
		}

		private sealed class ByReference : IEqualityComparer<Object>
		{
			internal static readonly ByReference Instance = new ByReference();

			public bool Equals(Object x, Object y)
			{
				return x == y;
			}

			public int GetHashCode(Object obj)
			{
				return RuntimeHelpers.GetHashCode(obj);
			}
		}

		private static readonly Feature s_zdoKeys = Features.Register("AllocZdoKeys", defaultOn: true, "Cooking stations and mine rocks reuse their ZDO key strings (\"slot\" + i, \"Health\" + i) instead of building new ones every frame or check.");

		private static readonly Feature s_overlap = Features.Register("AllocOverlap", defaultOn: true, "Physics.OverlapSphere in MonsterAI.FindClosestConsumableItem and ItemDrop.AutoStackItems reuses arrays.");

		private static readonly Feature s_projectiles = Features.Register("AllocProjectile", defaultOn: true, "Projectiles' hit rays (RaycastAll every physics step) reuse arrays.");

		private static readonly Feature s_projectileSpheres = Features.Register("AllocProjectileSphere", defaultOn: false, "Lab, off until AllocVerify confirms it: with AllocProjectile, projectiles with a ray radius (SphereCastAll) also reuse arrays. Unity's non-allocating sphere cast may normalize the direction once more, so hits could differ by float rounding.");

		private static readonly Feature s_spawn = Features.Register("AllocSpawnSystem", defaultOn: true, "Spawn systems hash each spawner's timer key once instead of building the string every second.");

		private static readonly Feature s_heightmap = Features.Register("AllocHeightmap", defaultOn: true, "A new zone's terrain collision mesh takes its indices from the game's list instead of a 96 KB array copy.");

		private static readonly Feature s_turret = Features.Register("AllocTurret", defaultOn: true, "Ballistas compare ammo against cached prefab names instead of reading (allocating) every ammo type's name every physics step.");

		private static readonly Feature s_verify = Features.Register("AllocVerify", defaultOn: false, "Lab: also runs the game's own call next to each Alloc* replacement, uses its answer and logs any difference. Slower.");

		internal static long VerifyChecks;

		internal static long VerifyMismatches;

		internal static long VerifyDrift;

		internal static long VerifyNoise;

		private static readonly MethodInfo s_intToString = AccessTools.Method(typeof(int), "ToString", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo s_concat2 = AccessTools.Method(typeof(string), "Concat", new Type[2]
		{
			typeof(string),
			typeof(string)
		}, (Type[])null);

		private static readonly MethodInfo s_concat3 = AccessTools.Method(typeof(string), "Concat", new Type[3]
		{
			typeof(string),
			typeof(string),
			typeof(string)
		}, (Type[])null);

		private static readonly MethodInfo s_format1 = AccessTools.Method(typeof(string), "Format", new Type[2]
		{
			typeof(string),
			typeof(object)
		}, (Type[])null);

		private static readonly MethodInfo s_stableHash = AccessTools.Method(typeof(StringExtensionMethods), "GetStableHashCode", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo s_getName = AccessTools.PropertyGetter(typeof(Object), "name");

		private static readonly MethodInfo s_listToArray = AccessTools.Method(typeof(List<int>), "ToArray", (Type[])null, (Type[])null);

		private static readonly MethodInfo s_setIndices = AccessTools.Method(typeof(Mesh), "SetIndices", new Type[3]
		{
			typeof(int[]),
			typeof(MeshTopology),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo s_overlap3 = AccessTools.Method(typeof(Physics), "OverlapSphere", new Type[3]
		{
			typeof(Vector3),
			typeof(float),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo s_raycastAll = AccessTools.Method(typeof(Physics), "RaycastAll", new Type[4]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(float),
			typeof(int)
		}, (Type[])null);

		private static readonly MethodInfo s_sphereCastAll = AccessTools.Method(typeof(Physics), "SphereCastAll", new Type[5]
		{
			typeof(Vector3),
			typeof(float),
			typeof(Vector3),
			typeof(float),
			typeof(int)
		}, (Type[])null);

		private static readonly FieldInfo s_spawnPrefab = AccessTools.Field(typeof(SpawnData), "m_prefab");

		private static readonly FieldInfo s_ammoField = AccessTools.Field(typeof(AmmoType), "m_ammo");

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

		private static readonly FieldInfo s_labels = AccessTools.Field(typeof(CodeInstruction), "labels");

		private static IndexedKeys[] s_keySets = new IndexedKeys[0];

		private static readonly ColliderPool s_consumablePool = new ColliderPool("MonsterAI.FindClosestConsumableItem");

		private static readonly ColliderPool s_autoStackPool = new ColliderPool("ItemDrop.AutoStackItems");

		private static readonly RaycastIntoFn s_raycastInto = Bind<RaycastIntoFn>(typeof(PhysicsScene), "Internal_RaycastNonAlloc");

		private static readonly SphereCastIntoFn s_sphereCastInto = Bind<SphereCastIntoFn>(typeof(PhysicsScene), "Internal_SphereCastNonAlloc");

		private static readonly HitPool s_rayPool = new HitPool("Projectile.FixedUpdate RaycastAll");

		private static readonly HitPool s_spherePool = new HitPool("Projectile.FixedUpdate SphereCastAll");

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

		private static string s_saltFormat;

		private static readonly string[] s_salts = new string[16];

		private static readonly Dictionary<Object, string> s_prefabNames = new Dictionary<Object, string>(ByReference.Instance);

		private static MethodInfo Ours(string name)
		{
			return AccessTools.DeclaredMethod(typeof(AllocFixesModule), name, (Type[])null, (Type[])null);
		}

		private static void Install(Harmony harmony)
		{
			Transpile(harmony, typeof(CookingStation), "GetSlot", "CookingStationKeys");
			Transpile(harmony, typeof(CookingStation), "SetSlot", "CookingStationKeys");
			Transpile(harmony, typeof(CookingStation), "IsEmpty", "CookingStationKeys");
			Transpile(harmony, typeof(CookingStation), "GetFreeSlot", "CookingStationKeys");
			Transpile(harmony, typeof(MineRock), "UpdateVisability", "MineRockKeys");
			Transpile(harmony, typeof(MonsterAI), "FindClosestConsumableItem", "ConsumableOverlap");
			Transpile(harmony, typeof(ItemDrop), "AutoStackItems", "AutoStackOverlap");
			Transpile(harmony, typeof(Projectile), "FixedUpdate", "ProjectileRays");
			Transpile(harmony, typeof(SpawnSystem), "UpdateSpawnList", "SpawnTimerKeys");
			Transpile(harmony, typeof(SpawnSystem), "UpdateSpawning", "SpawnSalts");
			Transpile(harmony, typeof(Heightmap), "RebuildCollisionMesh", "CollisionIndices");
			Transpile(harmony, typeof(Turret), "UpdateVisualBolt", "TurretAmmoNames");
			if (s_raycastInto == null || s_sphereCastInto == null)
			{
				EnginePlugin.Log.LogWarning((object)"AllocProjectile: Unity's PhysicsScene internals not found; projectile rays stay as in the game.");
			}
			s_spawn.Switched += delegate(bool on)
			{
				if (on)
				{
					s_spawnHashes.Clear();
				}
			};
			s_turret.Switched += delegate(bool on)
			{
				if (on)
				{
					s_prefabNames.Clear();
				}
			};
		}

		private static void Transpile(Harmony harmony, Type type, string method, string transpiler)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			string text = type.Name + "." + method;
			try
			{
				MethodInfo methodInfo = AccessTools.DeclaredMethod(type, method, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					EnginePlugin.Log.LogWarning((object)("AllocFixes: " + text + " not found, left as it is."));
					return;
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(Ours(transpiler))
				{
					priority = 0
				}, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception arg)
			{
				EnginePlugin.Log.LogError((object)$"AllocFixes: {text} not patched: {arg}");
			}
		}

		private static void Report(MethodBase original, string what, int n, int expected = 0)
		{
			string text = ((original != null) ? (original.DeclaringType?.Name + "." + original.Name) : "?") + ": " + what;
			if (!s_reported.TryGetValue(text, out var value) || value != n)
			{
				s_reported[text] = n;
				if (n == 0)
				{
					EnginePlugin.Log.LogWarning((object)("AllocFixes: " + text + ": not found (changed by another mod?), left as it is."));
				}
				else if (expected > 0 && n != expected)
				{
					EnginePlugin.Log.LogWarning((object)($"AllocFixes: {text}: {n} calls where the game has {expected} (added by another mod or an update?); " + "each pooled array may serve one call site, so left as it is."));
				}
				else
				{
					EnginePlugin.Log.LogInfo((object)$"AllocFixes: {text} x{n}");
				}
			}
		}

		private static bool IsAddressLoad(CodeInstruction ci)
		{
			if (!(ci.opcode == OpCodes.Ldarga_S) && !(ci.opcode == OpCodes.Ldarga) && !(ci.opcode == OpCodes.Ldloca_S))
			{
				return ci.opcode == OpCodes.Ldloca;
			}
			return true;
		}

		private static bool IsValueLoad(CodeInstruction ci)
		{
			OpCode opcode = ci.opcode;
			if (!(opcode == OpCodes.Ldloc_0) && !(opcode == OpCodes.Ldloc_1) && !(opcode == OpCodes.Ldloc_2) && !(opcode == OpCodes.Ldloc_3) && !(opcode == OpCodes.Ldloc_S) && !(opcode == OpCodes.Ldloc) && !(opcode == OpCodes.Ldarg_0) && !(opcode == OpCodes.Ldarg_1) && !(opcode == OpCodes.Ldarg_2) && !(opcode == OpCodes.Ldarg_3) && !(opcode == OpCodes.Ldarg_S))
			{
				return opcode == OpCodes.Ldarg;
			}
			return true;
		}

		private static bool Unlabeled(CodeInstruction ci)
		{
			if (s_labels?.GetValue(ci) is ICollection collection)
			{
				return collection.Count == 0;
			}
			return true;
		}

		private static int Find(List<CodeInstruction> code, int start, params Func<CodeInstruction, bool>[] pattern)
		{
			for (int i = Math.Max(0, start); i + pattern.Length <= code.Count; i++)
			{
				int j;
				for (j = 0; j < pattern.Length && pattern[j](code[i + j]); j++)
				{
				}
				if (j == pattern.Length)
				{
					return i;
				}
			}
			return -1;
		}

		private static void Set(CodeInstruction ci, OpCode opcode, object operand)
		{
			ci.opcode = opcode;
			ci.operand = operand;
		}

		private static void Mismatch(string site, string detail)
		{
			VerifyMismatches++;
			if (VerifyMismatches <= 50)
			{
				EnginePlugin.Log.LogWarning((object)("AllocVerify: " + site + " differs from the game's own call: " + detail));
			}
		}

		private static void Drift(string site, string detail)
		{
			VerifyDrift++;
			if (VerifyDrift <= 50)
			{
				EnginePlugin.Log.LogWarning((object)("AllocVerify: " + site + " hits the same colliders in the same order, but values differ: " + detail));
			}
		}

		private static void Noise(string site, string detail)
		{
			VerifyNoise++;
			if (VerifyNoise <= 20)
			{
				EnginePlugin.Log.LogInfo((object)("AllocVerify: " + site + " differs only where the game cannot notice: " + detail));
			}
		}

		private static IEnumerable<CodeInstruction> SwapCall(IEnumerable<CodeInstruction> code, MethodBase original, MethodInfo from, MethodInfo to)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			if (from != null)
			{
				foreach (CodeInstruction item in list)
				{
					if (CodeInstructionExtensions.Calls(item, from))
					{
						num++;
					}
				}
			}
			if (num == 1)
			{
				foreach (CodeInstruction item2 in list)
				{
					if (CodeInstructionExtensions.Calls(item2, from))
					{
						Set(item2, OpCodes.Call, to);
					}
				}
			}
			Report(original, from?.Name + " -> " + to.Name, num, 1);
			return list;
		}

		private static IEnumerable<CodeInstruction> CookingStationKeys(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			return CachedKeys(code, original, new string[2] { "slot", "slotstatus" });
		}

		private static IEnumerable<CodeInstruction> MineRockKeys(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			return CachedKeys(code, original, new string[1] { "Health" });
		}

		private static IEnumerable<CodeInstruction> CachedKeys(IEnumerable<CodeInstruction> code, MethodBase original, string[] prefixes)
		{
			MethodInfo operand = Ours("ZdoKey");
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			int start = 0;
			while ((start = Find(list, start, (CodeInstruction ci) => ci.opcode == OpCodes.Ldstr && ci.operand is string value && Array.IndexOf(prefixes, value) >= 0, (CodeInstruction ci) => IsAddressLoad(ci) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_intToString) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_concat2) && Unlabeled(ci))) >= 0)
			{
				Set(list[start + 2], OpCodes.Ldind_I4, null);
				Set(list[start + 3], OpCodes.Call, operand);
				num++;
				start += 4;
			}
			Report(original, "cached ZDO keys", num);
			return list;
		}

		private static IndexedKeys KeysFor(string prefix)
		{
			IndexedKeys[] array = s_keySets;
			for (int i = 0; i < array.Length; i++)
			{
				if ((object)array[i].Prefix == prefix)
				{
					return array[i];
				}
			}
			for (int j = 0; j < array.Length; j++)
			{
				if (array[j].Prefix == prefix)
				{
					return array[j];
				}
			}
			IndexedKeys indexedKeys = new IndexedKeys(prefix);
			IndexedKeys[] array2 = new IndexedKeys[array.Length + 1];
			Array.Copy(array, array2, array.Length);
			array2[array.Length] = indexedKeys;
			s_keySets = array2;
			return indexedKeys;
		}

		private static string ZdoKey(string prefix, int index)
		{
			if (!s_zdoKeys.On)
			{
				return prefix + index;
			}
			string text = KeysFor(prefix).Get(index);
			if (s_verify.On)
			{
				VerifyChecks++;
				string text2 = prefix + index;
				if (text2 != text)
				{
					Mismatch("ZDO key", "'" + text + "' vs '" + text2 + "'");
					return text2;
				}
			}
			return text;
		}

		private static IEnumerable<CodeInstruction> ConsumableOverlap(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			return SwapCall(code, original, s_overlap3, Ours("OverlapConsumable"));
		}

		private static IEnumerable<CodeInstruction> AutoStackOverlap(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			return SwapCall(code, original, s_overlap3, Ours("OverlapAutoStack"));
		}

		private static Collider[] OverlapConsumable(Vector3 position, float radius, int layerMask)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return s_consumablePool.OverlapSphere(position, radius, layerMask, (QueryTriggerInteraction)0);
		}

		private static Collider[] OverlapAutoStack(Vector3 position, float radius, int layerMask)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return s_autoStackPool.OverlapSphere(position, radius, layerMask, (QueryTriggerInteraction)0);
		}

		private static IEnumerable<CodeInstruction> ProjectileRays(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			return SwapCall(SwapCall(code, original, s_raycastAll, Ours("ProjectileRaycastAll")), original, s_sphereCastAll, Ours("ProjectileSphereCastAll"));
		}

		private static T Bind<T>(Type type, string name) where T : Delegate
		{
			try
			{
				MethodInfo methodInfo = AccessTools.DeclaredMethod(type, name, (Type[])null, (Type[])null);
				return (methodInfo == null) ? null : ((T)Delegate.CreateDelegate(typeof(T), methodInfo, throwOnBindFailure: false));
			}
			catch (Exception)
			{
				return null;
			}
		}

		private static RaycastHit[] ProjectileRaycastAll(Vector3 origin, Vector3 direction, float maxDistance, int layerMask)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!s_projectiles.On || s_raycastInto == null)
			{
				return Physics.RaycastAll(origin, direction, maxDistance, layerMask);
			}
			float magnitude = ((Vector3)(ref direction)).magnitude;
			if (!(magnitude > float.Epsilon))
			{
				return Array.Empty<RaycastHit>();
			}
			Ray ray = default(Ray);
			((Ray)(ref ray))..ctor(origin, direction / magnitude);
			int num = s_raycastInto(Physics.defaultPhysicsScene, ray, s_rayPool.Buffer, maxDistance, layerMask, (QueryTriggerInteraction)0);
			if (num >= s_rayPool.Buffer.Length)
			{
				RaycastHit[] array = Physics.RaycastAll(origin, direction, maxDistance, layerMask);
				s_rayPool.Grow(array.Length);
				return array;
			}
			RaycastHit[] array2 = s_rayPool.Take(num);
			if (s_verify.On)
			{
				return s_rayPool.Verify(array2, Physics.RaycastAll(origin, direction, maxDistance, layerMask));
			}
			return array2;
		}

		private static RaycastHit[] ProjectileSphereCastAll(Vector3 origin, float radius, Vector3 direction, float maxDistance, int layerMask)
		{
			//IL_001f: 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_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)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!s_projectiles.On || !s_projectileSpheres.On || s_sphereCastInto == null)
			{
				return Physics.SphereCastAll(origin, radius, direction, maxDistance, layerMask);
			}
			float magnitude = ((Vector3)(ref direction)).magnitude;
			if (!(magnitude > float.Epsilon))
			{
				return Array.Empty<RaycastHit>();
			}
			int num = s_sphereCastInto(Physics.defaultPhysicsScene, origin, radius, direction / magnitude, s_spherePool.Buffer, maxDistance, layerMask, (QueryTriggerInteraction)0);
			if (num >= s_spherePool.Buffer.Length)
			{
				RaycastHit[] array = Physics.SphereCastAll(origin, radius, direction, maxDistance, layerMask);
				s_spherePool.Grow(array.Length);
				return array;
			}
			RaycastHit[] array2 = s_spherePool.Take(num);
			if (s_verify.On)
			{
				return s_spherePool.Verify(array2, Physics.SphereCastAll(origin, radius, direction, maxDistance, layerMask));
			}
			return array2;
		}

		private static IEnumerable<CodeInstruction> SpawnTimerKeys(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			MethodInfo operand = Ours("SpawnTimerKey");
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			int start = 0;
			while ((start = Find(list, start, (CodeInstruction ci) => CodeInstructionExtensions.LoadsField(ci, s_spawnPrefab, false), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_getName) && Unlabeled(ci), (CodeInstruction ci) => IsAddressLoad(ci) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_intToString) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_concat3) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_stableHash) && Unlabeled(ci))) >= 0)
			{
				Set(list[start + 1], OpCodes.Nop, null);
				Set(list[start + 3], OpCodes.Ldind_I4, null);
				Set(list[start + 4], OpCodes.Nop, null);
				Set(list[start + 5], OpCodes.Call, operand);
				num++;
				start += 6;
			}
			Report(original, "spawn timer key hashes", num);
			return list;
		}

		private static IEnumerable<CodeInstruction> SpawnSalts(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			MethodInfo operand = Ours("SpawnSalt");
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			int start = 0;
			while ((start = Find(list, start, (CodeInstruction ci) => ci.opcode == OpCodes.Ldstr, (CodeInstruction ci) => IsValueLoad(ci) && Unlabeled(ci), (CodeInstruction ci) => ci.opcode == OpCodes.Box && ci.operand is Type type && type == typeof(int) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_format1) && Unlabeled(ci))) >= 0)
			{
				Set(list[start + 2], OpCodes.Nop, null);
				Set(list[start + 3], OpCodes.Call, operand);
				num++;
				start += 4;
			}
			Report(original, "spawn salts", num);
			return list;
		}

		private static int SpawnTimerKey(string salt, GameObject prefab, int index)
		{
			if (!s_spawn.On || prefab == null || !Object.op_Implicit((Object)(object)prefab))
			{
				return StringExtensionMethods.GetStableHashCode(salt + ((Object)prefab).name + index);
			}
			SpawnKey key = new SpawnKey(salt, prefab, index);
			if (!s_spawnHashes.TryGetValue(key, out var value))
			{
				value = StringExtensionMethods.GetStableHashCode(salt + ((Object)prefab).name + index);
				if (s_spawnHashes.Count >= 4096)
				{
					s_spawnHashes.Clear();
				}
				s_spawnHashes.Add(key, value);
			}
			else if (s_verify.On)
			{
				VerifyChecks++;
				int stableHashCode = StringExtensionMethods.GetStableHashCode(salt + ((Object)prefab).name + index);
				if (stableHashCode != value)
				{
					Mismatch("SpawnSystem timer key", $"{((Object)prefab).name} #{index}");
					s_spawnHashes[key] = stableHashCode;
					return stableHashCode;
				}
			}
			return value;
		}

		private static string SpawnSalt(string format, int i)
		{
			if (!s_spawn.On || format == null || (uint)i >= s_salts.Length)
			{
				return string.Format(format, i);
			}
			if ((object)format != s_saltFormat)
			{
				if (format != s_saltFormat)
				{
					Array.Clear(s_salts, 0, s_salts.Length);
				}
				s_saltFormat = format;
			}
			string text = s_salts[i] ?? (s_salts[i] = string.Format(format, i));
			if (s_verify.On)
			{
				VerifyChecks++;
				string text2 = string.Format(format, i);
				if (text2 != text)
				{
					Mismatch("SpawnSystem salt", "'" + text + "' vs '" + text2 + "'");
					return text2;
				}
			}
			return text;
		}

		private static IEnumerable<CodeInstruction> CollisionIndices(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			MethodInfo operand = Ours("SetCollisionIndices");
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			int start = 0;
			while ((start = Find(list, start, (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_listToArray), (CodeInstruction ci) => CodeInstructionExtensions.LoadsConstant(ci) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.LoadsConstant(ci) && Unlabeled(ci), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_setIndices) && Unlabeled(ci))) >= 0)
			{
				Set(list[start], OpCodes.Nop, null);
				Set(list[start + 3], OpCodes.Call, operand);
				num++;
				start += 4;
			}
			Report(original, "index uploads from the list", num);
			return list;
		}

		private static void SetCollisionIndices(Mesh mesh, List<int> indices, MeshTopology topology, int submesh)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!s_heightmap.On)
			{
				mesh.SetIndices(indices.ToArray(), topology, submesh);
			}
			else
			{
				mesh.SetIndices(indices, topology, submesh, true, 0);
			}
		}

		private static IEnumerable<CodeInstruction> TurretAmmoNames(IEnumerable<CodeInstruction> code, MethodBase original)
		{
			MethodInfo operand = Ours("AmmoPrefabName");
			List<CodeInstruction> list = new List<CodeInstruction>(code);
			int num = 0;
			int start = 0;
			while ((start = Find(list, start, (CodeInstruction ci) => CodeInstructionExtensions.LoadsField(ci, s_ammoField, false), (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_getName) && Unlabeled(ci))) >= 0)
			{
				Set(list[start + 1], OpCodes.Call, operand);
				num++;
				start += 2;
			}
			Report(original, "cached ammo names", num);
			return list;
		}

		private static string AmmoPrefabName(Object prefab)
		{
			if (!s_turret.On || prefab == null || !Object.op_Implicit(prefab))
			{
				return prefab.name;
			}
			if (!s_prefabNames.TryGetValue(prefab, out var value))
			{
				value = prefab.name;
				if (s_prefabNames.Count >= 4096)
				{
					s_prefabNames.Clear();
				}
				s_prefabNames.Add(prefab, value);
			}
			else if (s_verify.On)
			{
				VerifyChecks++;
				string name = prefab.name;
				if (name != value)
				{
					Mismatch("Turret ammo name", "'" + value + "' vs '" + name + "'");
					s_prefabNames[prefab] = name;
					return name;
				}
			}
			return value;
		}
	}
	[EngineModule]
	public static class AreaIndexModule
	{
		private sealed class Rec
		{
			internal EffectArea Area;

			internal Transform Tr;

			internal GameObject Go;

			internal Collider[] Cols = Array.Empty<Collider>();

			internal int State;

			internal int Slot = -1;

			internal bool Sampled;

			internal bool EverRigid;

			internal Matrix4x4 Pose;

			internal Bounds Raw;

			internal bool RawEmpty;

			internal Matrix4x4 GoodPose;

			internal Bounds GoodRaw;

			internal bool HasGood;

			internal Bounds PinRaw;

			internal Bounds Box;

			internal readonly List<long> Keys = new List<long>();

			internal bool Huge;

			internal int AuditCount;

			internal float Due;

			internal int Stamp;

			internal bool Dead;
		}

		private struct Queued
		{
			internal Rec Rec;

			internal int Stamp;
		}

		private sealed class ByReference : IEqualityComparer<EffectArea>
		{
			internal static readonly ByReference Instance = new ByReference();

			public bool Equals(EffectArea a, EffectArea b)
			{
				return a == b;
			}

			public int GetHashCode(EffectArea a)
			{
				return RuntimeHelpers.GetHashCode(a);
			}
		}

		internal static readonly Feature Index = Features.Register("AreaIndex", defaultOn: true, "EffectArea.IsPointInsideArea/GetBaseValue answer 'no area here' from a grid of the loaded effect areas instead of a physics overlap plus GetComponent per hit; any possible hit still runs the game's query.");

		internal static readonly Feature Verify = Features.Register("AreaIndexVerify", defaultOn: false, "Lab: after every 'no area' answer of AreaIndex the game's query runs too, its answer is used and any difference is counted and logged.");

		private const float CellSize = 32f;

		private const float StableSeconds = 1f;

		private const float LooseResampleSeconds = 10f;

		private const float LooseMargin = 8f;

		private const int PendingPerFrame = 128;

		private const int AuditPerFrame = 64;

		private const float AuditCycleSeconds = 4f;

		private const int AuditPerAnswer = 4;

		private const int DormantAuditPerFrame = 32;

		private const int SweepPerFrame = 16;

		private const int UnpinnedScanLimit = 256;

		private const int UnpinnedMatchLimit = 16;

		private const int MaxCellsPerArea = 64;

		private const float ForeignCheckSeconds = 10f;

		private const float ExtensionPeriod = 2f;

		private const string LabOwners = "valheim.realportal.lab";

		private const int Pending = 0;

		private const int Pinned = 1;

		private const int Loose = 2;

		private const int Dormant = 3;

		public static long Queries;

		public static long Proven;

		public static long Fallbacks;

		public static long Unpins;

		public static long Audits;

		public static long Wakes;

		public static long Reshapes;

		public static long LateRegistered;

		public static long VerifyChecks;

		public static long VerifyMismatches;

		public static long StealthCalls;

		public static long StealthRefreshCalls;

		public static int StealthLights;

		private static readonly Dictionary<EffectArea, Rec> s_recs = new Dictionary<EffectArea, Rec>(ByReference.Instance);

		private static readonly Dictionary<long, List<Rec>> s_cells = new Dictionary<long, List<Rec>>();

		private static readonly List<Rec> s_pinned = new List<Rec>();

		private static readonly List<Rec> s_unpinned = new List<Rec>();

		private static readonly List<Rec> s_dormant = new List<Rec>();

		private static readonly List<Rec> s_huge = new List<Rec>();

		private static readonly Queue<Queued> s_firstQ = new Queue<Queued>();

		private static readonly Queue<Queued> s_stableQ = new Queue<Queued>();

		private static readonly Queue<Queued> s_looseQ = new Queue<Queued>();

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

		private static readonly List<EffectArea> s_areaBuf = new List<EffectArea>();

		private static readonly Stack<List<Rec>> s_freeLists = new Stack<List<Rec>>();

		private static int s_frame = -1;

		private static int s_auditAt;

		private static int s_dormantAt;

		private static int s_sweepAt;

		private static int s_sweepAllAt;

		private static int s_answered;

		private static float s_lastUpkeep;

		private static float s_auditCredit;

		private static float s_dormantCredit;

		private static bool s_seeded;

		private static bool s_foreign;

		private static bool s_installed;

		private static bool s_broken;

		private static bool s_canDorm;

		private static bool s_extGated = true;

		private static float s_nextForeignCheck;

		private static MethodInfo s_inside;

		private static MethodInfo s_baseValue;

		private static MethodInfo s_getExtensions;

		private static FieldRef<CraftingStation, float> s_extTimer;

		private static int s_mismatchLogs;

		private static FieldRef<StealthSystem, float> s_lightUpdate;

		private static FieldRef<StealthSystem, Light[]> s_lights;

		private static long s_stealthRefreshTicks;

		private static long s_stealthPlainTicks;

		private static long s_stealthMaxTicks;

		private static float s_stampBefore;

		public static int Areas => s_recs.Count;

		public static int PinnedAreas => s_pinned.Count;

		public static int UnpinnedAreas => s_unpinned.Count;

		public static int DormantAreas => s_dormant.Count;

		public static int Cells => s_cells.Count;

		public static bool ForeignPatched => s_foreign;

		public static bool ExtensionsGated => s_extGated;

		public static double StealthRefreshMs
		{
			get
			{
				if (StealthRefreshCalls <= 0)
				{
					return 0.0;
				}
				return (double)s_stealthRefreshTicks * 1000.0 / (double)Stopwatch.Frequency / (double)StealthRefreshCalls;
			}
		}

		public static double StealthPlainMs
		{
			get
			{
				if (StealthCalls - StealthRefreshCalls <= 0)
				{
					return 0.0;
				}
				return (double)s_stealthPlainTicks * 1000.0 / (double)Stopwatch.Frequency / (double)(StealthCalls - StealthRefreshCalls);
			}
		}

		public static double StealthMaxMs => (double)s_stealthMaxTicks * 1000.0 / (double)Stopwatch.Frequency;

		public static string Describe()
		{
			return $"AreaIndex: on {Index.On}, foreign {s_foreign}, areas {s_recs.Count} (pinned {s_pinned.Count}, unpinned {s_unpinned.Count}, dormant {s_dormant.Count}, huge {s_huge.Count}), cells {s_cells.Count}, " + $"queries {Queries}, none answered {Proven}, to the game {Fallbacks}, audits {Audits}, unpins {Unpins}, wakes {Wakes}, reshapes {Reshapes} (gated {s_extGated}), late {LateRegistered}, verify {VerifyChecks}/{VerifyMismatches} mismatches; " + $"stealth light: calls {StealthCalls}, refreshes {StealthRefreshCalls}, lights {StealthLights}, refresh {StealthRefreshMs:F3} ms, plain {StealthPlainMs:F3} ms, max {StealthMaxMs:F3} ms";
		}

		private static void Install(Harmony harmony)
		{
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			//IL_0237: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Expected O, but got Unknown
			//IL_025e: Expected O, but got Unknown
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Expected O, but got Unknown
			//IL_0304: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_01c8: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Expected O, but got Unknown
			Type typeFromHandle = typeof(AreaIndexModule);
			s_inside = AccessTools.DeclaredMethod(typeof(EffectArea), "IsPointInsideArea", (Type[])null, (Type[])null);
			s_baseValue = AccessTools.DeclaredMethod(typeof(EffectArea), "GetBaseValue", (Type[])null, (Type[])null);
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(EffectArea), "Awake", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(EffectArea), "OnDestroy", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(EffectArea), "OnEnable", (Type[])null, (Type[])null);
			s_getExtensions = AccessTools.DeclaredMethod(typeof(CraftingStation), "GetExtensions", (Type[])null, (Type[])null);
			try
			{
				FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(CraftingStation), "m_updateExtensionTimer");
				if ((object)fieldInfo != null && fieldInfo.FieldType == typeof(float))
				{
					s_extTimer = AccessTools.FieldRefAccess<CraftingStation, float>("m_updateExtensionTimer");
				}
			}
			catch (Exception)
			{
				s_extTimer = null;
			}
			if (s_inside == null || s_baseValue == null || methodInfo == null || methodInfo2 == null)
			{
				EnginePlugin.Log.LogWarning((object)"AreaIndex: an EffectArea method is missing (game update?), effect area queries stay as in the game.");
			}
			else if (s_getExtensions == null || s_extTimer == null)
			{
				EnginePlugin.Log.LogWarning((object)"AreaIndex: CraftingStation.GetExtensions or m_updateExtensionTimer is missing (game update?), effect area queries stay as in the game.");
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeFromHandle, "AwakeAfter", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeFromHandle, "DestroyBefore", (Type[])null)
				{
					priority = 800
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)s_getExtensions, new HarmonyMethod(typeFromHandle, "ExtensionsBefore", (Type[])null)
				{
					priority = 800
				}, new HarmonyMethod(typeFromHandle, "ExtensionsAfter", (Type[])null)
				{
					priority = 0
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo3 != null)
				{
					try
					{
						harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeFromHandle, "EnableAfter", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						s_canDorm = true;
					}
					catch (Exception ex2)
					{
						EnginePlugin.Log.LogWarning((object)("AreaIndex: EffectArea.OnEnable not patched, inactive areas are tested like pending ones: " + ex2.Message));
					}
				}
				harmony.Patch((MethodBase)s_inside, new HarmonyMethod(typeFromHandle, "InsideBefore", (Type[])null), new HarmonyMethod(typeFromHandle, "InsideAfter", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)s_baseValue, new HarmonyMethod(typeFromHandle, "BaseValueBefore", (Type[])null), new HarmonyMethod(typeFromHandle, "BaseValueAfter", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				s_installed = true;
				Index.Switched += delegate
				{
					StandDown();
				};
			}
			try
			{
				MethodInfo methodInfo4 = AccessTools.DeclaredMethod(typeof(StealthSystem), "GetLightLevel", (Type[])null, (Type[])null);
				s_lightUpdate = AccessTools.FieldRefAccess<StealthSystem, float>("m_lastLightListUpdate");
				s_lights = AccessTools.FieldRefAccess<StealthSystem, Light[]>("m_allLights");
				if (methodInfo4 != null)
				{
					harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeFromHandle, "LightBefore", (Type[])null)
					{
						priority = 800
					}, new HarmonyMethod(typeFromHandle, "LightAfter", (Type[])null)
					{
						priority = 0
					}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex3)
			{
				EnginePlugin.Log.LogWarning((object)("AreaIndex: StealthSystem.GetLightLevel timing not installed: " + ex3.Message));
			}
		}

		private static void AwakeAfter(EffectArea __instance)
		{
			if (s_broken)
			{
				return;
			}
			try
			{
				Register(__instance, late: false);
			}
			catch (Exception e)
			{
				Break(e);
			}
		}

		private static void DestroyBefore(EffectArea __instance)
		{
			if (s_broken)
			{
				return;
			}
			try
			{
				if (__instance != null && s_recs.TryGetValue(__instance, out var value))
				{
					Drop(value);
				}
			}
			catch (Exception e)
			{
				Break(e);
			}
		}

		private static void EnableAfter(EffectArea __instance)
		{
			if (!s_seeded || s_broken)
			{
				return;
			}
			try
			{
				if (__instance != null && s_recs.TryGetValue(__instance, out var value))
				{
					Wake(value);
				}
			}
			catch (Exception e)
			{
				Break(e);
			}
		}

		private static void ExtensionsBefore(CraftingStation __instance, out float __state)
		{
			__state = float.NaN;
			if (!s_seeded || s_broken)
			{
				return;
			}
			try
			{
				if (!s_extGated || !(s_extTimer.Invoke(__instance) < 2f))
				{
					__state = RadiusOf(__instance.m_effectAreaCollider);
				}
			}
			catch (Exception e)
			{
				Break(e);
			}
		}

		private static void ExtensionsAfter(CraftingStation __instance, float __state)
		{
			if (float.IsNaN(__state) || !s_seeded || s_broken)
			{
				return;
			}
			try
			{
				Collider effectAreaCollider = __instance.m_effectAreaCollider;
				if ((Object)(object)effectAreaCollider == (Object)null || RadiusOf(effectAreaCollider).Equals(__state))
				{
					return;
				}
				Reshapes++;
				s_areaBuf.Clear();
				((Component)effectAreaCollider).GetComponents<EffectArea>(s_areaBuf);
				for (int i = 0; i < s_areaBuf.Count; i++)
				{
					EffectArea val = s_areaBuf[i];
					if (s_recs.TryGetValue(val, out var value))
					{
						Wake(value);
					}
					else
					{
						Register(val, late: true);
					}
				}
				s_areaBuf.Clear();
			}
			catch (Exception e)
			{
				s_areaBuf.Clear();
				Break(e);
			}
		}

		private static float RadiusOf(Collider c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return float.NaN;
			}
			SphereCollider val = (SphereCollider)(object)((c is SphereCollider) ? c : null);
			if (val != null)
			{
				return val.radius;
			}
			CapsuleCollider val2 = (CapsuleCollider)(object)((c is CapsuleCollider) ? c : null);
			if (val2 != null)
			{
				return val2.radius;
			}
			return float.NaN;
		}

		private static void Break(Exception e)
		{
			if (!s_broken)
			{
				s_broken = true;
				s_seeded = false;
				ManualLogSource log = EnginePlugin.Log;
				if (log != null)
				{
					log.LogError((object)("AreaIndex: index failed, effect area queries go to the game for the rest of the session: " + e));
				}
				s_firstQ.Clear();
				s_stableQ.Clear();
				s_looseQ.Clear();
				s_recs.Clear();
				s_cells.Clear();
				s_pinned.Clear();
				s_unpinned.Clear();
				s_dormant.Clear();
				s_huge.Clear();
				s_freeLists.Clear();
			}
		}

		private static void StandDown()
		{
			s_seeded = false;
			s_firstQ.Clear();
			s_stableQ.Clear();
			s_looseQ.Clear();
		}

		private static void Register(EffectArea area, bool late)
		{
			if (!((Object)(object)area == (Object)null) && !s_recs.ContainsKey(area))
			{
				Rec rec = new Rec
				{
					Area = area,
					Tr = ((Component)area).transform,
					State = 0
				};
				s_recs.Add(area, rec);
				Add(s_unpinned, rec);
				if (late)
				{
					LateRegistered++;
				}
				if (s_seeded)
				{
					Queue(s_firstQ, rec, 0f);
				}
			}
		}

		private static void Drop(Rec r)
		{
			r.Dead = true;
			s_recs.Remove(r.Area);
			if (r.State == 1)
			{
				Unindex(r);
			}
			else if (r.State == 3)
			{
				RemoveAt(s_dormant, r);
			}
			else
			{
				RemoveAt(s_unpinned, r);
			}
		}

		private static void Wake(Rec r)
		{
			if (s_seeded && !r.Dead && (r.State != 0 || r.Sampled))
			{
				if (r.State == 1)
				{
					Unindex(r);
					Add(s_unpinned, r);
				}
				else if (r.State == 3)
				{
					RemoveAt(s_dormant, r);
					Add(s_unpinned, r);
				}
				r.State = 0;
				r.Sampled = false;
				Wakes++;
				Queue(s_firstQ, r, 0f);
			}
		}

		private static void Sleep(Rec r)
		{
			r.State = 3;
			r.Stamp++;
			Add(s_dormant, r);
		}

		private static bool CanDorm(Rec r)
		{
			if (s_canDorm && r.Go != null && !r.Go.activeInHierarchy)
			{
				return ((Behaviour)r.Area).enabled;
			}
			return false;
		}

		private static void Repend(Rec r, Matrix4x4 pose, Bounds raw, bool empty, float now)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Unindex(r);
			Add(s_unpinned, r);
			Note(r, pose, raw, empty);
			Queue(s_stableQ, r, now + 1f);
		}

		private static void Note(Rec r, Matrix4x4 pose, Bounds raw, bool empty)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			r.Sampled = true;
			r.Pose = pose;
			r.Raw = raw;
			r.RawEmpty = empty;
			if (!empty)
			{
				r.GoodPose = pose;
				r.GoodRaw = raw;
				r.HasGood = true;
			}
		}

		private static void Queue(Queue<Queued> queue, Rec r, float due)
		{
			r.Due = due;
			r.Stamp++;
			queue.Enqueue(new Queued
			{
				Rec = r,
				Stamp = r.Stamp
			});
		}

		private static void Sample(Rec r, out Matrix4x4 pose, out Bounds raw, out bool empty, out bool rigid)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (r.Go == null)
			{
				r.Go = ((Component)r.Area).gameObject;
			}
			s_cols.Clear();
			((Component)r.Area).GetComponents<Collider>(s_cols);
			if (!SameColliders(r.Cols, s_cols))
			{
				r.Cols = s_cols.ToArray();
			}
			s_cols.Clear();
			pose = r.Tr.localToWorldMatrix;
			raw = default(Bounds);
			empty = true;
			rigid = false;
			Collider[] cols = r.Cols;
			foreach (Collider val in cols)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if ((Object)(object)val.attachedRigidbody != (Object)null)
				{
					rigid = true;
				}
				Bounds bounds = val.bounds;
				if (!IsEmpty(bounds))
				{
					if (empty)
					{
						raw = bounds;
						empty = false;
					}
					else
					{
						((Bounds)(ref raw)).Encapsulate(bounds);
					}
				}
			}
		}

		private static void Peek(Rec r, out Matrix4x4 pose, out Bounds raw, out bool empty)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			pose = r.Tr.localToWorldMatrix;
			raw = default(Bounds);
			empty = true;
			Collider[] cols = r.Cols;
			foreach (Collider val in cols)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Bounds bounds = val.bounds;
				if (!IsEmpty(bounds))
				{
					if (empty)
					{
						raw = bounds;
						empty = false;
					}
					else
					{
						((Bounds)(ref raw)).Encapsulate(bounds);
					}
				}
			}
		}

		private static bool RigidOutOfScene(Rec r)
		{
			return (Object)(object)((Component)r.Tr).GetComponentInParent<Rigidbody>(true) != (Object)null;
		}

		private static bool SameColliders(Collider[] have, List<Collider> now)
		{
			if (have.Length != now.Count)
			{
				return false;
			}
			for (int i = 0; i < have.Length; i++)
			{
				if (have[i] != now[i])
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsEmpty(Bounds b)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (((Bounds)(ref b)).extents.x == 0f && ((Bounds)(ref b)).extents.y == 0f && ((Bounds)(ref b)).extents.z == 0f && ((Bounds)(ref b)).center.x == 0f && ((Bounds)(ref b)).center.y == 0f)
			{
				return ((Bounds)(ref b)).center.z == 0f;
			}
			return false;
		}

		private static void Maintain()
		{
			int frameCount = Time.frameCount;
			if (frameCount != s_frame)
			{
				s_frame = frameCount;
				float unscaledTime = Time.unscaledTime;
				if (!s_seeded)
				{
					Reseed(unscaledTime);
				}
				int budget = 128;
				Drain(s_firstQ, unscaledTime, ref budget);
				Drain(s_stableQ, unscaledTime, ref budget);
				Drain(s_looseQ, unscaledTime, ref budget);
				float num = unscaledTime - s_lastUpkeep;
				s_lastUpkeep = unscaledTime;
				if (!(num >= 0f))
				{
					num = 0f;
				}
				else if (num > 1f)
				{
					num = 1f;
				}
				s_auditCredit = Math.Min(64f, s_auditCredit + (float)s_pinned.Count * num / 4f + (float)(4 * s_answered));
				s_dormantCredit = Math.Min(32f, s_dormantCredit + (float)s_dormant.Count * num / 4f);
				s_answered = 0;
				AuditPinned(unscaledTime);
				AuditDormant();
				Sweep(EffectArea.Instances, ref s_sweepAt);
				SweepAll(EffectArea.GetAllAreas(), ref s_sweepAllAt);
			}
		}

		private sta

plugins/RealPortal.Burst.dll

Decompiled a day ago
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[CompilerGenerated]
[EditorBrowsable(EditorBrowsableState.Never)]
[GeneratedCode("Unity.MonoScriptGenerator.MonoScriptInfoGenerator", null)]
internal class UnitySourceGeneratedAssemblyMonoScriptTypes_v1
{
	private struct MonoScriptData
	{
		public byte[] FilePathsData;

		public byte[] TypesData;

		public int TotalTypes;

		public int TotalFiles;

		public bool IsEditorOnly;
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	private static MonoScriptData Get()
	{
		return new MonoScriptData
		{
			FilePathsData = new byte[186]
			{
				0, 0, 0, 1, 0, 0, 0, 37, 92, 65,
				115, 115, 101, 116, 115, 92, 82, 101, 97, 108,
				80, 111, 114, 116, 97, 108, 46, 66, 117, 114,
				115, 116, 92, 66, 117, 114, 115, 116, 74, 111,
				98, 115, 46, 99, 115, 0, 0, 0, 1, 0,
				0, 0, 36, 92, 65, 115, 115, 101, 116, 115,
				92, 82, 101, 97, 108, 80, 111, 114, 116, 97,
				108, 46, 66, 117, 114, 115, 116, 92, 80, 114,
				111, 98, 101, 74, 111, 98, 46, 99, 115, 0,
				0, 0, 2, 0, 0, 0, 40, 92, 65, 115,
				115, 101, 116, 115, 92, 82, 101, 97, 108, 80,
				111, 114, 116, 97, 108, 46, 66, 117, 114, 115,
				116, 92, 80, 114, 111, 120, 121, 67, 117, 108,
				108, 74, 111, 98, 46, 99, 115, 0, 0, 0,
				10, 0, 0, 0, 41, 92, 65, 115, 115, 101,
				116, 115, 92, 82, 101, 97, 108, 80, 111, 114,
				116, 97, 108, 46, 66, 117, 114, 115, 116, 92,
				80, 114, 111, 120, 121, 86, 105, 101, 119, 74,
				111, 98, 115, 46, 99, 115
			},
			TypesData = new byte[463]
			{
				0, 0, 0, 0, 26, 82, 101, 97, 108, 80,
				111, 114, 116, 97, 108, 46, 66, 117, 114, 115,
				116, 124, 66, 117, 114, 115, 116, 74, 111, 98,
				115, 0, 0, 0, 0, 25, 82, 101, 97, 108,
				80, 111, 114, 116, 97, 108, 46, 66, 117, 114,
				115, 116, 124, 80, 114, 111, 98, 101, 74, 111,
				98, 0, 0, 0, 0, 29, 82, 101, 97, 108,
				80, 111, 114, 116, 97, 108, 46, 66, 117, 114,
				115, 116, 124, 80, 114, 111, 120, 121, 67, 117,
				108, 108, 74, 111, 98, 0, 0, 0, 0, 32,
				82, 101, 97, 108, 80, 111, 114, 116, 97, 108,
				46, 66, 117, 114, 115, 116, 124, 80, 114, 111,
				120, 121, 67, 111, 109, 112, 97, 99, 116, 74,
				111, 98, 0, 0, 0, 0, 25, 82, 101, 97,
				108, 80, 111, 114, 116, 97, 108, 46, 66, 117,
				114, 115, 116, 124, 86, 105, 101, 119, 73, 110,
				115, 116, 0, 0, 0, 0, 26, 82, 101, 97,
				108, 80, 111, 114, 116, 97, 108, 46, 66, 117,
				114, 115, 116, 124, 86, 105, 101, 119, 82, 97,
				110, 103, 101, 0, 0, 0, 0, 24, 82, 101,
				97, 108, 80, 111, 114, 116, 97, 108, 46, 66,
				117, 114, 115, 116, 124, 86, 105, 101, 119, 79,
				117, 116, 0, 0, 0, 0, 29, 82, 101, 97,
				108, 80, 111, 114, 116, 97, 108, 46, 66, 117,
				114, 115, 116, 124, 86, 105, 101, 119, 84, 101,
				109, 112, 108, 97, 116, 101, 0, 0, 0, 0,
				28, 82, 101, 97, 108, 80, 111, 114, 116, 97,
				108, 46, 66, 117, 114, 115, 116, 124, 86, 105,
				101, 119, 86, 97, 114, 105, 97, 110, 116, 0,
				0, 0, 0, 32, 82, 101, 97, 108, 80, 111,
				114, 116, 97, 108, 46, 66, 117, 114, 115, 116,
				124, 86, 105, 101, 119, 86, 97, 114, 105, 97,
				110, 116, 80, 97, 114, 116, 0, 0, 0, 0,
				25, 82, 101, 97, 108, 80, 111, 114, 116, 97,
				108, 46, 66, 117, 114, 115, 116, 124, 86, 105,
				101, 119, 80, 97, 114, 116, 0, 0, 0, 0,
				26, 82, 101, 97, 108, 80, 111, 114, 116, 97,
				108, 46, 66, 117, 114, 115, 116, 124, 86, 105,
				101, 119, 67, 111, 110, 115, 116, 0, 0, 0,
				0, 33, 82, 101, 97, 108, 80, 111, 114, 116,
				97, 108, 46, 66, 117, 114, 115, 116, 124, 80,
				114, 111, 120, 121, 86, 105, 101, 119, 67, 117,
				108, 108, 74, 111, 98, 0, 0, 0, 0, 33,
				82, 101, 97, 108, 80, 111, 114, 116, 97, 108,
				46, 66, 117, 114, 115, 116, 124, 80, 114, 111,
				120, 121, 86, 105, 101, 119, 69, 109, 105, 116,
				74, 111, 98
			},
			TotalFiles = 4,
			TotalTypes = 14,
			IsEditorOnly = false
		};
	}
}
namespace RealPortal.Burst;

public static class BurstJobs
{
	public const int ApiVersion = 3;

	public const int ModeBurst = 1;

	public const int ModeManaged = 2;

	public const int ProbeLength = 16;

	public static readonly string[] JobNames = new string[4] { "ProxyCullJob", "ProxyCompactJob", "ProxyViewCullJob", "ProxyViewEmitJob" };

	public const int ProbeBatches = 16;

	public static int[] Probe()
	{
		//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)
		NativeArray<int> result = default(NativeArray<int>);
		result..ctor(16, (Allocator)3, (NativeArrayOptions)1);
		try
		{
			IJobExtensions.Run<ProbeJob>(new ProbeJob
			{
				Result = result
			});
			return result.ToArray();
		}
		finally
		{
			result.Dispose();
		}
	}

	public static int[] ExpectedLayout()
	{
		return new int[15]
		{
			3,
			UnsafeUtility.SizeOf<ProxyCullJob>(),
			UnsafeUtility.SizeOf<ProxyCompactJob>(),
			UnsafeUtility.SizeOf<ProxyViewCullJob>(),
			UnsafeUtility.SizeOf<ProxyViewEmitJob>(),
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0
		};
	}

	public static int[] ViewSizes()
	{
		return new int[7]
		{
			UnsafeUtility.SizeOf<ViewInst>(),
			UnsafeUtility.SizeOf<ViewRange>(),
			UnsafeUtility.SizeOf<ViewOut>(),
			UnsafeUtility.SizeOf<ViewTemplate>(),
			UnsafeUtility.SizeOf<ViewVariant>(),
			UnsafeUtility.SizeOf<ViewVariantPart>(),
			UnsafeUtility.SizeOf<ViewPart>()
		};
	}

	public static int[] ProbeJobs()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_004d: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		NativeArray<float4> spheres = default(NativeArray<float4>);
		spheres..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<float4> planes = default(NativeArray<float4>);
		planes..ctor(6, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<int> visible = default(NativeArray<int>);
		visible..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<int> batchCounts = default(NativeArray<int>);
		batchCounts..ctor(16, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<int> visibleCount = default(NativeArray<int>);
		visibleCount..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		try
		{
			ProxyCullJob obj = new ProxyCullJob
			{
				Spheres = spheres,
				Planes = planes,
				Visible = visible,
				BatchCounts = batchCounts,
				BatchSize = 0
			};
			JobHandle val = default(JobHandle);
			val = IJobForExtensions.ScheduleParallel<ProxyCullJob>(obj, 16, 1, val);
			((JobHandle)(ref val)).Complete();
			int num = 1;
			for (int i = 0; i < 16; i++)
			{
				if (num != 1)
				{
					break;
				}
				num = batchCounts[i];
			}
			ProxyCompactJob obj2 = new ProxyCompactJob
			{
				Visible = visible,
				BatchCounts = batchCounts,
				VisibleCount = visibleCount,
				BatchSize = 0
			};
			val = default(JobHandle);
			val = IJobExtensions.Schedule<ProxyCompactJob>(obj2, val);
			((JobHandle)(ref val)).Complete();
			return new int[4]
			{
				num,
				visibleCount[0],
				ProbeViewCull(),
				ProbeViewEmit()
			};
		}
		finally
		{
			spheres.Dispose();
			planes.Dispose();
			visible.Dispose();
			batchCounts.Dispose();
			visibleCount.Dispose();
		}
	}

	private static int ProbeViewCull()
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		NativeArray<int> val = default(NativeArray<int>);
		val..ctor(16, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewInst> page = default(NativeArray<ViewInst>);
		page..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewRange> ranges = default(NativeArray<ViewRange>);
		ranges..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewTemplate> val2 = default(NativeArray<ViewTemplate>);
		val2..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewVariant> variants = default(NativeArray<ViewVariant>);
		variants..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<byte> rowFlags = default(NativeArray<byte>);
		rowFlags..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<Vector4> planes = default(NativeArray<Vector4>);
		planes..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewOut> val3 = default(NativeArray<ViewOut>);
		val3..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		try
		{
			ProxyViewCullJob obj = new ProxyViewCullJob
			{
				Page = page,
				Ranges = ranges,
				Templates = val2,
				LodSets = val2,
				Variants = variants,
				RowFlags = rowFlags,
				Planes = planes,
				Out = val3,
				Room = val,
				RangeBase = -1
			};
			JobHandle val4 = default(JobHandle);
			val4 = IJobParallelForExtensions.Schedule<ProxyViewCullJob>(obj, 16, 1, val4);
			((JobHandle)(ref val4)).Complete();
			return AllBurst(val);
		}
		finally
		{
			val.Dispose();
			page.Dispose();
			ranges.Dispose();
			val2.Dispose();
			variants.Dispose();
			rowFlags.Dispose();
			planes.Dispose();
			val3.Dispose();
		}
	}

	private static int ProbeViewEmit()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		NativeArray<int> val = default(NativeArray<int>);
		val..ctor(16, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewInst> page = default(NativeArray<ViewInst>);
		page..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewRange> ranges = default(NativeArray<ViewRange>);
		ranges..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewOut> cull = default(NativeArray<ViewOut>);
		cull..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewVariant> variants = default(NativeArray<ViewVariant>);
		variants..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewVariantPart> variantParts = default(NativeArray<ViewVariantPart>);
		variantParts..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<ViewPart> parts = default(NativeArray<ViewPart>);
		parts..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<int> val2 = default(NativeArray<int>);
		val2..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<Matrix4x4> m = default(NativeArray<Matrix4x4>);
		m..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		NativeArray<Vector4> s = default(NativeArray<Vector4>);
		s..ctor(1, (Allocator)3, (NativeArrayOptions)1);
		try
		{
			ProxyViewEmitJob obj = new ProxyViewEmitJob
			{
				Page = page,
				Ranges = ranges,
				Cull = cull,
				Variants = variants,
				VariantParts = variantParts,
				Parts = parts,
				BatchDraw = val2,
				Base = val2,
				Key = val2,
				M = m,
				S = s,
				Filled = val,
				Visible = val2,
				Casters = val2,
				SpecialCount = val2,
				Special = val2,
				RowDrawn = val2,
				RangeBase = -1
			};
			JobHandle val3 = default(JobHandle);
			val3 = IJobParallelForExtensions.Schedule<ProxyViewEmitJob>(obj, 16, 1, val3);
			((JobHandle)(ref val3)).Complete();
			return AllBurst(val);
		}
		finally
		{
			val.Dispose();
			page.Dispose();
			ranges.Dispose();
			cull.Dispose();
			variants.Dispose();
			variantParts.Dispose();
			parts.Dispose();
			val2.Dispose();
			m.Dispose();
			s.Dispose();
		}
	}

	private static int AllBurst(NativeArray<int> modes)
	{
		for (int i = 0; i < modes.Length; i++)
		{
			if (modes[i] != 1)
			{
				return modes[i];
			}
		}
		return 1;
	}

	public static JobHandle ScheduleViewCull(NativeArray<byte> page, NativeArray<byte> ranges, NativeArray<byte> templates, NativeArray<byte> lodSets, NativeArray<byte> variants, NativeArray<byte> rowFlags, NativeArray<Vector4> planes, NativeArray<byte> outs, NativeArray<int> room, int rangeBase, int rangeCount, int casterPlanes, int maxLod, uint skip, Vector4 cam, Vector4 prevCam, Vector4 light, int flags, JobHandle dependsOn)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		return IJobParallelForExtensions.Schedule<ProxyViewCullJob>(new ProxyViewCullJob
		{
			Page = page.Reinterpret<ViewInst>(1),
			Ranges = ranges.Reinterpret<ViewRange>(1),
			Templates = templates.Reinterpret<ViewTemplate>(1),
			LodSets = lodSets.Reinterpret<ViewTemplate>(1),
			Variants = variants.Reinterpret<ViewVariant>(1),
			RowFlags = rowFlags,
			Planes = planes,
			Out = outs.Reinterpret<ViewOut>(1),
			Room = room,
			RangeBase = rangeBase,
			CasterPlanes = casterPlanes,
			MaxLod = maxLod,
			Skip = skip,
			Cam = new Vector3(cam.x, cam.y, cam.z),
			K = cam.w,
			PrevCam = new Vector3(prevCam.x, prevCam.y, prevCam.z),
			PrevK = prevCam.w,
			Light = new Vector3(light.x, light.y, light.z),
			Margin = light.w,
			HasPrev = ((flags & 1) != 0),
			Animated = ((flags & 2) != 0),
			Shadows = ((flags & 4) != 0),
			CameraSideCasts = ((flags & 8) != 0)
		}, rangeCount, 1, dependsOn);
	}

	public static JobHandle ScheduleViewEmit(NativeArray<byte> page, NativeArray<byte> ranges, NativeArray<byte> cull, NativeArray<byte> variants, NativeArray<byte> variantParts, NativeArray<byte> parts, NativeArray<int> batchDraw, NativeArray<int> bases, NativeArray<int> key, NativeArray<Matrix4x4> m, NativeArray<Vector4> s, NativeArray<int> filled, NativeArray<int> visible, NativeArray<int> casters, NativeArray<int> specialCount, NativeArray<int> special, NativeArray<int> rowDrawn, int rangeBase, int rangeCount, int mask, int frame, bool obliqueClip, JobHandle dependsOn)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		return IJobParallelForExtensions.Schedule<ProxyViewEmitJob>(new ProxyViewEmitJob
		{
			Page = page.Reinterpret<ViewInst>(1),
			Ranges = ranges.Reinterpret<ViewRange>(1),
			Cull = cull.Reinterpret<ViewOut>(1),
			Variants = variants.Reinterpret<ViewVariant>(1),
			VariantParts = variantParts.Reinterpret<ViewVariantPart>(1),
			Parts = parts.Reinterpret<ViewPart>(1),
			BatchDraw = batchDraw,
			Base = bases,
			Key = key,
			M = m,
			S = s,
			Filled = filled,
			Visible = visible,
			Casters = casters,
			SpecialCount = specialCount,
			Special = special,
			RowDrawn = rowDrawn,
			RangeBase = rangeBase,
			Mask = mask,
			Frame = frame,
			ObliqueClip = obliqueClip
		}, rangeCount, 1, dependsOn);
	}

	public static int BatchCount(int length, int batchSize)
	{
		return length / batchSize + ((length % batchSize != 0) ? 1 : 0);
	}

	public static JobHandle ScheduleCull(NativeArray<float4> spheres, NativeArray<float4> planes, NativeArray<int> visible, NativeArray<int> batchCounts, NativeArray<int> visibleCount, int batchSize, JobHandle dependsOn)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		CheckCullArguments(spheres.Length, planes.Length, visible.Length, batchCounts.Length, visibleCount.Length, batchSize);
		JobHandle val = IJobForExtensions.ScheduleParallel<ProxyCullJob>(new ProxyCullJob
		{
			Spheres = spheres,
			Planes = planes,
			Visible = visible,
			BatchCounts = batchCounts,
			BatchSize = batchSize
		}, batchCounts.Length, 1, dependsOn);
		return IJobExtensions.Schedule<ProxyCompactJob>(new ProxyCompactJob
		{
			Visible = visible,
			BatchCounts = batchCounts,
			BatchSize = batchSize,
			VisibleCount = visibleCount
		}, val);
	}

	public static void CheckCullArguments(int spheres, int planes, int visible, int batchCounts, int visibleCount, int batchSize)
	{
		if (batchSize <= 0)
		{
			throw new ArgumentOutOfRangeException("batchSize", batchSize, "must be positive");
		}
		if (planes != 6)
		{
			throw new ArgumentException($"planes must hold 6 planes, has {planes}");
		}
		if (visible < spheres)
		{
			throw new ArgumentException($"visible must hold {spheres} indices, has {visible}");
		}
		if (batchCounts != BatchCount(spheres, batchSize))
		{
			throw new ArgumentException($"batchCounts must hold {BatchCount(spheres, batchSize)} counts, has {batchCounts}");
		}
		if (visibleCount < 1)
		{
			throw new ArgumentException("visibleCount must hold 1 value");
		}
	}
}
[BurstCompile(CompileSynchronously = true)]
public struct ProbeJob : IJob
{
	public NativeArray<int> Result;

	public void Execute()
	{
		Put(0, 1);
		MarkManaged();
		Put(1, 3);
		Put(2, UnsafeUtility.SizeOf<ProxyCullJob>());
		Put(3, UnsafeUtility.SizeOf<ProxyCompactJob>());
		Put(4, UnsafeUtility.SizeOf<ProxyViewCullJob>());
		Put(5, UnsafeUtility.SizeOf<ProxyViewEmitJob>());
	}

	private void Put(int index, int value)
	{
		if (index < Result.Length)
		{
			Result[index] = value;
		}
	}

	[BurstDiscard]
	private void MarkManaged()
	{
		Put(0, 2);
	}
}
[BurstCompile(/*Could not decode attribute arguments.*/)]
public struct ProxyCullJob : IJobFor
{
	[ReadOnly]
	public NativeArray<float4> Spheres;

	[ReadOnly]
	public NativeArray<float4> Planes;

	[NativeDisableParallelForRestriction]
	public NativeArray<int> Visible;

	public NativeArray<int> BatchCounts;

	public int BatchSize;

	public void Execute(int batch)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		if (BatchSize <= 0)
		{
			BatchCounts[batch] = 1;
			MarkManaged(batch);
			return;
		}
		float4 p = Planes[0];
		float4 p2 = Planes[1];
		float4 p3 = Planes[2];
		float4 p4 = Planes[3];
		float4 p5 = Planes[4];
		float4 p6 = Planes[5];
		int num = batch * BatchSize;
		int num2 = num + math.min(BatchSize, Spheres.Length - num);
		int num3 = 0;
		for (int i = num; i < num2; i++)
		{
			float4 val = Spheres[i];
			float num4 = 0f - val.w;
			if (!(Distance(p, val) < num4) && !(Distance(p2, val) < num4) && !(Distance(p3, val) < num4) && !(Distance(p4, val) < num4) && !(Distance(p5, val) < num4) && !(Distance(p6, val) < num4))
			{
				Visible[num + num3] = i;
				num3++;
			}
		}
		BatchCounts[batch] = num3;
	}

	[BurstDiscard]
	private void MarkManaged(int batch)
	{
		BatchCounts[batch] = 2;
	}

	private static float Distance(float4 p, float4 s)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		return p.x * s.x + p.y * s.y + p.z * s.z + p.w;
	}
}
[BurstCompile(/*Could not decode attribute arguments.*/)]
public struct ProxyCompactJob : IJob
{
	public NativeArray<int> Visible;

	[ReadOnly]
	public NativeArray<int> BatchCounts;

	public NativeArray<int> VisibleCount;

	public int BatchSize;

	public void Execute()
	{
		if (BatchSize <= 0)
		{
			VisibleCount[0] = 1;
			MarkManaged();
			return;
		}
		int num = 0;
		for (int i = 0; i < BatchCounts.Length; i++)
		{
			int num2 = i * BatchSize;
			int num3 = BatchCounts[i];
			if (num2 != num)
			{
				for (int j = 0; j < num3; j++)
				{
					Visible[num + j] = Visible[num2 + j];
				}
			}
			num += num3;
		}
		VisibleCount[0] = num;
	}

	[BurstDiscard]
	private void MarkManaged()
	{
		VisibleCount[0] = 2;
	}
}
public struct ViewInst
{
	public Matrix4x4 Root;

	public Vector3 Center;

	public float Radius;

	public Vector3 LodRef;

	public float LodSize;

	public int Template;

	public int Variant;

	public int LodSet;

	public uint Flags;

	public int Row;
}
public struct ViewRange
{
	public int Start;

	public int Count;

	public int Out;

	public int DistantOnly;
}
public struct ViewOut
{
	public byte Vis;

	public byte Lod;

	public byte Prev;

	public byte Pad;

	public float Fade;
}
public struct ViewTemplate
{
	public int Prefab;

	public int PartStart;

	public int PartCount;

	public int LodCount;

	public int FadeMode;

	public bool AnimateCrossFading;

	public bool LodFadeInOut;

	public float LodSize;

	public Vector3 LodLocalRef;

	public Matrix4x4 LodLocal;

	public Vector4 HeightsA;

	public Vector4 HeightsB;

	public Vector4 FadeA;

	public Vector4 FadeB;

	public float Height(int level)
	{
		if (level >= 4)
		{
			return ((Vector4)(ref HeightsB))[level - 4];
		}
		return ((Vector4)(ref HeightsA))[level];
	}

	public float FadeWidth(int level)
	{
		if (level >= 4)
		{
			return ((Vector4)(ref FadeB))[level - 4];
		}
		return ((Vector4)(ref FadeA))[level];
	}
}
public struct ViewVariant
{
	public int Template;

	public int PartStart;

	public int PartCount;

	public int LodSet;

	public Vector3 Center;

	public Vector3 Extents;
}
public struct ViewVariantPart
{
	public int Part;

	public int Batch;

	public int Mpb;

	public int LodMask;

	public int Run;
}
public struct ViewPart
{
	public Matrix4x4 Local;

	public Vector3 Center;

	public Vector3 Extents;

	public int Batch;

	public int LodMask;

	public int Template;
}
internal static class ViewConst
{
	public const uint Created = 1u;

	public const uint Distant = 8u;

	public const byte NoLevel = 254;

	public const byte Culled = byte.MaxValue;

	public const byte RowFading = 1;

	public const byte RowBorn = 2;

	public const int LodAll = 255;

	public const int CrossFade = 1;

	public const int ShadowsOff = 0;

	public const int TwoSided = 2;

	public const int ShadowsOnly = 3;
}
[BurstCompile(/*Could not decode attribute arguments.*/)]
public struct ProxyViewCullJob : IJobParallelFor
{
	[ReadOnly]
	public NativeArray<ViewInst> Page;

	[ReadOnly]
	public NativeArray<ViewRange> Ranges;

	[ReadOnly]
	public NativeArray<ViewTemplate> Templates;

	[ReadOnly]
	public NativeArray<ViewTemplate> LodSets;

	[ReadOnly]
	public NativeArray<ViewVariant> Variants;

	[ReadOnly]
	public NativeArray<byte> RowFlags;

	[ReadOnly]
	public NativeArray<Vector4> Planes;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<ViewOut> Out;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Room;

	public int RangeBase;

	public int CasterPlanes;

	public int MaxLod;

	public Vector3 Cam;

	public Vector3 PrevCam;

	public Vector3 Light;

	public float K;

	public float PrevK;

	public float Margin;

	public bool HasPrev;

	public bool Animated;

	public bool Shadows;

	public bool CameraSideCasts;

	public uint Skip;

	public void Execute(int index)
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		if (RangeBase < 0)
		{
			Room[index] = 1;
			MarkManaged(index);
			return;
		}
		ViewRange viewRange = Ranges[RangeBase + index];
		uint skip = Skip;
		int num = 0;
		for (int i = 0; i < viewRange.Count; i++)
		{
			ViewInst viewInst = Page[viewRange.Start + i];
			ViewOut o = default(ViewOut);
			uint flags = viewInst.Flags;
			if ((flags & skip) == 0 && (viewRange.DistantOnly == 0 || (flags & 8) != 0))
			{
				Vector3 center = viewInst.Center;
				float num2 = viewInst.Radius + Margin;
				Vector4 val = Planes[6];
				if ((o.Vis = (byte)((val.x * center.x + val.y * center.y + val.z * center.z + val.w < 0f - num2) ? ((CameraSideCasts && Sweep(7, CasterPlanes, center, num2, Light)) ? 3 : 0) : (Inside(center, num2) ? 1 : ((Shadows && Sweep(7, CasterPlanes, center, num2, Light)) ? 2 : 0)))) != 0)
				{
					num += Variants[viewInst.Variant].PartCount;
					ViewTemplate td = ((viewInst.LodSet >= 0) ? LodSets[viewInst.LodSet] : Templates[viewInst.Template]);
					if (td.LodCount == 0)
					{
						o.Lod = (o.Prev = 254);
					}
					else
					{
						o.Lod = Select(in td, viewInst.LodSize, Vector3.Distance(Cam, viewInst.LodRef), K, out o.Fade);
						o.Prev = (HasPrev ? Select(in td, viewInst.LodSize, Vector3.Distance(PrevCam, viewInst.LodRef), PrevK, out var _) : o.Lod);
						o.Pad = (byte)(Special(in td, in o, (byte)(((uint)viewInst.Row < (uint)RowFlags.Length) ? RowFlags[viewInst.Row] : 0)) ? 1 : 0);
					}
				}
			}
			Out[viewRange.Out + i] = o;
		}
		Room[RangeBase + index] = num;
	}

	[BurstDiscard]
	private void MarkManaged(int index)
	{
		Room[index] = 2;
	}

	private bool Special(in ViewTemplate td, in ViewOut o, byte rowFlags)
	{
		if (td.LodFadeInOut && (rowFlags & 2) != 0)
		{
			return true;
		}
		if (td.FadeMode == 1 && td.AnimateCrossFading && Animated)
		{
			if ((rowFlags & 1) == 0)
			{
				return o.Prev != o.Lod;
			}
			return true;
		}
		if (td.FadeMode == 1 && o.Lod != byte.MaxValue)
		{
			return o.Fade > 0f;
		}
		return false;
	}

	private bool Inside(Vector3 c, float rad)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 6; i++)
		{
			Vector4 val = Planes[i];
			if (val.x * c.x + val.y * c.y + val.z * c.z + val.w < 0f - rad)
			{
				return false;
			}
		}
		return true;
	}

	private bool Sweep(int from, int count, Vector3 c, float r, Vector3 ray)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		float num2 = 1f;
		for (int i = from; i < from + count; i++)
		{
			Vector4 val = Planes[i];
			float num3 = val.x * c.x + val.y * c.y + val.z * c.z + val.w + r;
			float num4 = val.x * ray.x + val.y * ray.y + val.z * ray.z;
			if (num4 == 0f)
			{
				if (num3 < 0f)
				{
					return false;
				}
				continue;
			}
			float num5 = (0f - num3) / num4;
			if (num4 > 0f)
			{
				if (num5 > num)
				{
					num = num5;
				}
			}
			else if (num5 < num2)
			{
				num2 = num5;
			}
			if (num > num2)
			{
				return false;
			}
		}
		return true;
	}

	private byte Select(in ViewTemplate td, float size, float d, float k, out float fade)
	{
		fade = 0f;
		float num = ((d > 1E-06f) ? (size * k / d) : float.MaxValue);
		int lodCount = td.LodCount;
		for (int i = ((MaxLod < lodCount - 1) ? MaxLod : (lodCount - 1)); i < lodCount; i++)
		{
			float num2 = td.Height(i);
			if (num < num2)
			{
				continue;
			}
			if (td.FadeMode == 1 && !td.AnimateCrossFading)
			{
				float num3 = ((i == 0) ? 1f : td.Height(i - 1));
				float num4 = td.FadeWidth(i) * (num3 - num2);
				if (num4 > 0f && num < num2 + num4)
				{
					fade = (num - num2) / num4;
				}
			}
			return (byte)i;
		}
		return byte.MaxValue;
	}
}
[BurstCompile(/*Could not decode attribute arguments.*/)]
public struct ProxyViewEmitJob : IJobParallelFor
{
	[ReadOnly]
	public NativeArray<ViewInst> Page;

	[ReadOnly]
	public NativeArray<ViewRange> Ranges;

	[ReadOnly]
	public NativeArray<ViewOut> Cull;

	[ReadOnly]
	public NativeArray<ViewVariant> Variants;

	[ReadOnly]
	public NativeArray<ViewVariantPart> VariantParts;

	[ReadOnly]
	public NativeArray<ViewPart> Parts;

	[ReadOnly]
	public NativeArray<int> BatchDraw;

	[ReadOnly]
	public NativeArray<int> Base;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Key;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<Matrix4x4> M;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<Vector4> S;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Filled;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Visible;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Casters;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> SpecialCount;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> Special;

	[NativeDisableParallelForRestriction]
	[NativeDisableContainerSafetyRestriction]
	public NativeArray<int> RowDrawn;

	public int RangeBase;

	public int Mask;

	public int Frame;

	public bool ObliqueClip;

	public void Execute(int index)
	{
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		if (RangeBase < 0)
		{
			Filled[index] = 1;
			MarkManaged(index);
			return;
		}
		int num = RangeBase + index;
		ViewRange viewRange = Ranges[num];
		int num2 = Base[num];
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		Vector4 val = default(Vector4);
		for (int i = 0; i < viewRange.Count; i++)
		{
			ViewOut viewOut = Cull[viewRange.Out + i];
			if (viewOut.Vis == 0)
			{
				continue;
			}
			if (viewOut.Vis == 1)
			{
				num4++;
			}
			else
			{
				num5++;
			}
			if (viewOut.Pad != 0)
			{
				Special[viewRange.Out + num6++] = i;
				continue;
			}
			ViewInst viewInst = Page[viewRange.Start + i];
			ViewVariant viewVariant = Variants[viewInst.Variant];
			((Vector4)(ref val))..ctor(viewInst.Center.x, viewInst.Center.y, viewInst.Center.z, viewInst.Radius);
			bool flag = false;
			int j = viewVariant.PartStart;
			for (int num7 = viewVariant.PartStart + viewVariant.PartCount; j < num7; j++)
			{
				ViewVariantPart viewVariantPart = VariantParts[j];
				if (viewOut.Lod != 254 && viewVariantPart.LodMask != 255 && (viewOut.Lod >= 8 || (viewVariantPart.LodMask & (1 << (int)viewOut.Lod)) == 0))
				{
					continue;
				}
				int num8 = (((uint)viewVariantPart.Batch < (uint)BatchDraw.Length) ? BatchDraw[viewVariantPart.Batch] : (-1));
				if (num8 < 0)
				{
					continue;
				}
				int num9 = num8 & 0xFF;
				int num10 = num8 >> 8;
				if (num9 >= 32 || (Mask & (1 << num9)) == 0)
				{
					continue;
				}
				int num11;
				if (viewOut.Vis == 1)
				{
					num11 = num10;
				}
				else
				{
					if (num10 == 0)
					{
						continue;
					}
					num11 = ((num10 == 2 && (viewOut.Vis == 2 || ObliqueClip)) ? 2 : 3);
				}
				int num12 = num2 + num3++;
				Key[num12] = viewVariantPart.Run * 4 + num11;
				M[num12] = viewInst.Root * Parts[viewVariantPart.Part].Local;
				S[num12] = val;
				flag = true;
			}
			if (flag && viewOut.Vis == 1 && (viewInst.Flags & 1) == 0 && (uint)viewInst.Row < (uint)RowDrawn.Length)
			{
				RowDrawn[viewInst.Row] = Frame;
			}
		}
		Filled[num] = num3;
		Visible[num] = num4;
		Casters[num] = num5;
		SpecialCount[num] = num6;
	}

	[BurstDiscard]
	private void MarkManaged(int index)
	{
		Filled[index] = 2;
	}
}

patchers/RealPortal.Preloader.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]
[assembly: AssemblyCompany("RealPortal.Preloader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RealPortal.Preloader")]
[assembly: AssemblyTitle("RealPortal.Preloader")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RealPortal.Preloader;

public static class Patcher
{
	private sealed class Plan
	{
		public TypeDefinition Zdo;

		public FieldDefinition Row;

		public readonly List<MethodDefinition> NoInline = new List<MethodDefinition>();

		public readonly List<MethodDefinition> ResetsRow = new List<MethodDefinition>();
	}

	public const string RowField = "rp_row";

	private static ManualLogSource s_log;

	public static IEnumerable<string> TargetDLLs => new string[1] { "assembly_valheim.dll" };

	private static ManualLogSource Log => s_log ?? (s_log = Logger.CreateLogSource("RealPortal.Preloader"));

	public static void Patch(AssemblyDefinition assembly)
	{
		try
		{
			Run(assembly.MainModule);
		}
		catch (Exception ex)
		{
			Log.LogError((object)("assembly_valheim: patching for the ZDO journal failed part way; the engine's self-check decides what it can use. " + ex));
		}
	}

	private static void Run(ModuleDefinition module)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Expected O, but got Unknown
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		List<string> list = new List<string>();
		Plan plan = Find(module, list);
		if (list.Count > 0)
		{
			Log.LogError((object)("assembly_valheim left UNTOUCHED: the ZDO journal's patch targets are not as expected (game update?): " + string.Join("; ", list.ToArray()) + ". The engine's journal runs on Harmony only, with rows in a dictionary; check its self-check line in the log."));
			return;
		}
		List<string> list2 = new List<string>();
		List<string> list3 = new List<string>();
		if (plan.Row == null)
		{
			plan.Row = new FieldDefinition("rp_row", (FieldAttributes)6, module.TypeSystem.Int32);
			plan.Zdo.Fields.Add(plan.Row);
			list2.Add("added field ZDO.rp_row");
		}
		else
		{
			list3.Add("field ZDO.rp_row");
		}
		List<string> list4 = new List<string>();
		List<string> list5 = new List<string>();
		foreach (MethodDefinition item in plan.NoInline)
		{
			if (item.NoInlining && !item.AggressiveInlining)
			{
				list5.Add(Name(item));
				continue;
			}
			item.NoInlining = true;
			item.AggressiveInlining = false;
			list4.Add(Name(item));
		}
		if (list4.Count > 0)
		{
			list2.Add("NoInlining on " + string.Join(", ", list4.ToArray()));
		}
		if (list5.Count > 0)
		{
			list3.Add("NoInlining on " + string.Join(", ", list5.ToArray()));
		}
		List<string> list6 = new List<string>();
		List<string> list7 = new List<string>();
		foreach (MethodDefinition item2 in plan.ResetsRow)
		{
			if (StoresRow(item2))
			{
				list7.Add(Name(item2));
				continue;
			}
			ILProcessor iLProcessor = item2.Body.GetILProcessor();
			Instruction val = item2.Body.Instructions[0];
			iLProcessor.InsertBefore(val, iLProcessor.Create(OpCodes.Ldarg_0));
			iLProcessor.InsertBefore(val, iLProcessor.Create(OpCodes.Ldc_I4_M1));
			iLProcessor.InsertBefore(val, iLProcessor.Create(OpCodes.Stfld, (FieldReference)(object)plan.Row));
			list6.Add(Name(item2));
		}
		if (list6.Count > 0)
		{
			list2.Add("rp_row = -1 at the start of " + string.Join(", ", list6.ToArray()));
		}
		if (list7.Count > 0)
		{
			list3.Add("rp_row = -1 in " + string.Join(", ", list7.ToArray()));
		}
		if (list2.Count == 0)
		{
			Log.LogInfo((object)("assembly_valheim already patched for the ZDO journal, nothing changed (" + string.Join("; ", list3.ToArray()) + ")"));
		}
		else
		{
			Log.LogInfo((object)("assembly_valheim patched for the ZDO journal: " + string.Join("; ", list2.ToArray()) + ((list3.Count > 0) ? (" (already there: " + string.Join("; ", list3.ToArray()) + ")") : "")));
		}
	}

	private static Plan Find(ModuleDefinition module, List<string> missing)
	{
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Invalid comparison between Unknown and I4
		Plan plan = new Plan();
		TypeDefinition type = module.GetType("ZDO");
		TypeDefinition type2 = module.GetType("ZDOMan");
		TypeDefinition type3 = module.GetType("ZoneSystem");
		TypeDefinition val = ((type3 != null) ? ((IEnumerable<TypeDefinition>)type3.NestedTypes).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition t) => ((MemberReference)t).Name == "SectorIndex")) : null);
		if (type == null)
		{
			missing.Add("type ZDO");
		}
		if (type2 == null)
		{
			missing.Add("type ZDOMan");
		}
		if (val == null || !((TypeReference)val).IsValueType)
		{
			missing.Add("struct ZoneSystem.SectorIndex");
		}
		if (missing.Count > 0)
		{
			return plan;
		}
		plan.Zdo = type;
		string fullName = ((MemberReference)val).FullName;
		NoInline(type, "IncreaseDataRevision", new string[0]);
		NoInline(type, "IncreaseOwnerRevision", new string[0]);
		NoInline(type, "SetSector", new string[1] { fullName });
		NoInline(type2, "AddToSector", new string[2] { "ZDO", fullName });
		NoInline(type2, "InitialAddToSector", new string[2] { "ZDO", fullName });
		NoInline(type2, "RemoveFromSector", new string[2] { "ZDO", fullName });
		MethodDefinition val2 = Method(type, "Reset", new string[0], missing);
		if (val2 != null)
		{
			plan.ResetsRow.Add(val2);
		}
		List<MethodDefinition> list = ((IEnumerable<MethodDefinition>)type.Methods).Where((MethodDefinition m) => m.IsConstructor && !m.IsStatic).ToList();
		if (list.Count == 0)
		{
			missing.Add("a ZDO instance constructor");
		}
		foreach (MethodDefinition item in list)
		{
			if (!item.HasBody || item.Body.Instructions.Count == 0)
			{
				missing.Add("a body for " + Name(item));
			}
			else
			{
				plan.ResetsRow.Add(item);
			}
		}
		FieldDefinition val3 = ((IEnumerable<FieldDefinition>)type.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition f) => ((MemberReference)f).Name == "rp_row"));
		if (val3 != null && (val3.IsStatic || !val3.IsPublic || (int)((FieldReference)val3).FieldType.MetadataType != 8))
		{
			missing.Add("ZDO.rp_row exists but is not a public instance int (" + ((MemberReference)((FieldReference)val3).FieldType).FullName + ")");
		}
		plan.Row = val3;
		return plan;
		void NoInline(TypeDefinition type4, string name, string[] parameters)
		{
			MethodDefinition val4 = Method(type4, name, parameters, missing);
			if (val4 != null)
			{
				plan.NoInline.Add(val4);
			}
		}
	}

	private static MethodDefinition Method(TypeDefinition type, string name, string[] parameters, List<string> missing)
	{
		string text = ((MemberReference)type).Name + "." + name + "(" + string.Join(", ", parameters) + ")";
		List<MethodDefinition> list = ((IEnumerable<MethodDefinition>)type.Methods).Where((MethodDefinition m) => ((MemberReference)m).Name == name && !m.IsStatic && m.HasBody && (int)((MethodReference)m).ReturnType.MetadataType == 1 && ((MethodReference)m).Parameters.Count == parameters.Length && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).SequenceEqual(parameters)).ToList();
		if (list.Count == 1)
		{
			return list[0];
		}
		missing.Add((list.Count == 0) ? (text + " not found") : (text + " ambiguous"));
		return null;
	}

	private static bool StoresRow(MethodDefinition m)
	{
		return ((IEnumerable<Instruction>)m.Body.Instructions).Any(delegate(Instruction i)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			OpCode opCode = i.OpCode;
			if ((int)((OpCode)(ref opCode)).Code == 122)
			{
				object operand = i.Operand;
				FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
				if (val != null && ((MemberReference)val).Name == "rp_row")
				{
					return ((MemberReference)((MemberReference)val).DeclaringType).FullName == "ZDO";
				}
			}
			return false;
		});
	}

	private static string Name(MethodDefinition m)
	{
		return ((MemberReference)m.DeclaringType).Name + "." + ((MemberReference)m).Name;
	}
}