Decompiled source of Voxel Levels v1.0.0

EmpressVoxelLevels.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: AssemblyInformationalVersion("1.8.0")]
[assembly: AssemblyProduct("EmpressVoxelLevels")]
[assembly: AssemblyTitle("EmpressVoxelLevels")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.REPO.VoxelLevels
{
	internal static class EmpressVoxelAccess
	{
		private static readonly FieldInfo LevelGeneratorInstanceField = AccessTools.Field(typeof(LevelGenerator), "Instance");

		private static readonly FieldRef<LevelGenerator, GameObject> LevelParentRef = BuildLevelParentRef();

		private static readonly FieldRef<LevelGenerator, bool> GeneratedRef = BuildGeneratedRef();

		internal static LevelGenerator LevelGeneratorInstance()
		{
			if (LevelGeneratorInstanceField == null)
			{
				return null;
			}
			try
			{
				object? value = LevelGeneratorInstanceField.GetValue(null);
				return (LevelGenerator)((value is LevelGenerator) ? value : null);
			}
			catch
			{
				return null;
			}
		}

		internal static GameObject LevelParent(LevelGenerator generator)
		{
			if ((Object)(object)generator == (Object)null || LevelParentRef == null)
			{
				return null;
			}
			try
			{
				return LevelParentRef.Invoke(generator);
			}
			catch
			{
				return null;
			}
		}

		internal static bool Generated(LevelGenerator generator)
		{
			if ((Object)(object)generator == (Object)null || GeneratedRef == null)
			{
				return false;
			}
			try
			{
				return GeneratedRef.Invoke(generator);
			}
			catch
			{
				return false;
			}
		}

		internal static bool RunIsLevel()
		{
			try
			{
				return SemiFunc.RunIsLevel();
			}
			catch
			{
				return false;
			}
		}

		internal static bool RunIsShop()
		{
			try
			{
				return SemiFunc.RunIsShop();
			}
			catch
			{
				return false;
			}
		}

		internal static bool RunIsLobby()
		{
			try
			{
				return SemiFunc.RunIsLobby();
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsMultiplayer()
		{
			try
			{
				return SemiFunc.IsMultiplayer();
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsMasterClientOrSingleplayer()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				return false;
			}
		}

		private static FieldRef<LevelGenerator, GameObject> BuildLevelParentRef()
		{
			try
			{
				return AccessTools.FieldRefAccess<LevelGenerator, GameObject>("LevelParent");
			}
			catch
			{
				return null;
			}
		}

		private static FieldRef<LevelGenerator, bool> BuildGeneratedRef()
		{
			try
			{
				return AccessTools.FieldRefAccess<LevelGenerator, bool>("Generated");
			}
			catch
			{
				return null;
			}
		}
	}
	[BepInPlugin("Empress.REPO.VoxelLevels", "Empress Voxel Levels", "1.8.0")]
	public sealed class EmpressVoxelLevelsPlugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "Empress.REPO.VoxelLevels";

		internal const string PluginName = "Empress Voxel Levels";

		internal const string PluginVersion = "1.8.0";

		private Harmony _harmony;

		private EmpressVoxelWorld _world;

		internal static EmpressVoxelLevelsPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> VoxelizeStartRoom { get; private set; }

		internal static ConfigEntry<bool> VoxelizeShop { get; private set; }

		internal static ConfigEntry<bool> VoxelizeLobby { get; private set; }

		internal static ConfigEntry<float> VoxelSize { get; private set; }

		internal static ConfigEntry<float> ProbeHorizontal { get; private set; }

		internal static ConfigEntry<float> ProbeVertical { get; private set; }

		internal static ConfigEntry<bool> ReplaceColliders { get; private set; }

		internal static ConfigEntry<bool> HideOriginalRenderers { get; private set; }

		internal static ConfigEntry<float> GunBreakRadius { get; private set; }

		internal static ConfigEntry<float> ExplosionRadiusBase { get; private set; }

		internal static ConfigEntry<float> ExplosionRadiusMultiplier { get; private set; }

		internal static ConfigEntry<bool> ProtectCeilings { get; private set; }

		internal static ConfigEntry<bool> EverythingDestructible { get; private set; }

		internal static ConfigEntry<int> OpeningWiden { get; private set; }

		internal static ConfigEntry<bool> FreeTrappedLoot { get; private set; }

		internal static ConfigEntry<bool> AlignFloorTops { get; private set; }

		internal static ConfigEntry<int> CeilingRaise { get; private set; }

		internal static ConfigEntry<bool> RemoveDoors { get; private set; }

		internal static ConfigEntry<int> MaxVoxels { get; private set; }

		internal static ConfigEntry<int> BuildBudgetPerFrame { get; private set; }

		internal static ConfigEntry<bool> DebrisEnabled { get; private set; }

		internal static ConfigEntry<int> MaxDebris { get; private set; }

		internal static ConfigEntry<float> DebrisLifetime { get; private set; }

		private void Awake()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			((Component)this).transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			_world = ((Component)this).gameObject.AddComponent<EmpressVoxelWorld>();
			_harmony = new Harmony("Empress.REPO.VoxelLevels");
			_harmony.PatchAll(typeof(EmpressVoxelLevelsPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded Empress Voxel Levels v1.8.0");
		}

		internal static EmpressVoxelWorld World()
		{
			if (!((Object)(object)Instance == (Object)null))
			{
				return Instance._world;
			}
			return null;
		}

		private void BindConfig()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Expected O, but got Unknown
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Expected O, but got Unknown
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Expected O, but got Unknown
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Voxelize generated levels and allow weapons to carve them.");
			VoxelizeStartRoom = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VoxelizeStartRoom", true, "Voxelize the truck and start room shell so it matches the rest of the level. Truck equipment stays intact.");
			VoxelizeShop = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VoxelizeShop", true, "Voxelize the shop level. Shop terminals and keepers stay intact.");
			VoxelizeLobby = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VoxelizeLobby", true, "Voxelize the lobby where upgrades are applied. Interactive fixtures stay intact.");
			VoxelSize = ((BaseUnityPlugin)this).Config.Bind<float>("Voxel", "VoxelSize", 1f, new ConfigDescription("Edge length of a single voxel in world units. Lower is finer and heavier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			ProbeHorizontal = ((BaseUnityPlugin)this).Config.Bind<float>("Voxel", "ProbeHorizontal", 0.25f, new ConfigDescription("Horizontal thickness of the surface probe as a fraction of a voxel. Lower keeps corridors and doorways open.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.5f), Array.Empty<object>()));
			ProbeVertical = ((BaseUnityPlugin)this).Config.Bind<float>("Voxel", "ProbeVertical", 0.5f, new ConfigDescription("Vertical thickness of the surface probe as a fraction of a voxel. Keep high so floors and ceilings never gap.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.5f), Array.Empty<object>()));
			ReplaceColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "ReplaceColliders", true, "Replace the original level collision with solid voxel collision so destroyed walls become real openings.");
			HideOriginalRenderers = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "HideOriginalRenderers", true, "Hide the original level meshes so only the voxel shell is visible.");
			ProtectCeilings = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "ProtectCeilings", true, "Keep ceiling voxels indestructible alongside floors. Ignored when EverythingDestructible is on.");
			EverythingDestructible = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "EverythingDestructible", true, "Allow every voxel including floors and ceilings to be destroyed.");
			OpeningWiden = ((BaseUnityPlugin)this).Config.Bind<int>("Voxel", "OpeningWiden", 2, new ConfigDescription("Erode doorway jambs and lintels by this many cells to widen and heighten module passages. Straight walls are kept.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>()));
			FreeTrappedLoot = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "FreeTrappedLoot", true, "Carve voxels out of valuables and items so loot never spawns trapped inside a block.");
			AlignFloorTops = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "AlignFloorTops", true, "Snap floor voxel tops to the real floor surface so players, valuables and props sit at the correct height instead of sinking.");
			CeilingRaise = ((BaseUnityPlugin)this).Config.Bind<int>("Voxel", "CeilingRaise", 4, new ConfigDescription("Render room ceilings this many voxel blocks higher for headroom. Only genuine overhead ceilings with open space above are raised; floors, platforms and stacked rooms are never touched.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
			RemoveDoors = ((BaseUnityPlugin)this).Config.Bind<bool>("Voxel", "RemoveDoors", true, "Remove level hinge doors so they do not glitch against the voxel floor. Truck and shop doors are kept.");
			MaxVoxels = ((BaseUnityPlugin)this).Config.Bind<int>("Voxel", "MaxVoxels", 250000, new ConfigDescription("Safety cap on rendered voxels per level.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10000, 2000000), Array.Empty<object>()));
			BuildBudgetPerFrame = ((BaseUnityPlugin)this).Config.Bind<int>("Voxel", "BuildBudgetPerFrame", 1500, new ConfigDescription("Voxel operations processed per frame while building.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(200, 20000), Array.Empty<object>()));
			GunBreakRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Destruction", "GunBreakRadius", 1.6f, new ConfigDescription("World radius carved by a single bullet impact.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), Array.Empty<object>()));
			ExplosionRadiusBase = ((BaseUnityPlugin)this).Config.Bind<float>("Destruction", "ExplosionRadiusBase", 1.8f, new ConfigDescription("Base world radius carved by an explosion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 12f), Array.Empty<object>()));
			ExplosionRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Destruction", "ExplosionRadiusMultiplier", 9f, new ConfigDescription("Explosion size is multiplied by this to extend the carve radius.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			DebrisEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debris", "DebrisEnabled", true, "Spawn short lived debris cubes when a wall voxel is destroyed.");
			MaxDebris = ((BaseUnityPlugin)this).Config.Bind<int>("Debris", "MaxDebris", 120, new ConfigDescription("Maximum simultaneous debris cubes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 600), Array.Empty<object>()));
			DebrisLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Debris", "DebrisLifetime", 2.5f, new ConfigDescription("Seconds before a debris cube is removed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 8f), Array.Empty<object>()));
		}
	}
	[HarmonyPatch(typeof(ItemGun), "ShootBullet")]
	internal static class EmpressVoxelGunPatch
	{
		private static void Postfix(Vector3 _endPosition, bool _hit)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (_hit && EmpressVoxelLevelsPlugin.Enabled.Value && EmpressVoxelAccess.IsMasterClientOrSingleplayer())
			{
				EmpressVoxelWorld empressVoxelWorld = EmpressVoxelLevelsPlugin.World();
				if ((Object)(object)empressVoxelWorld != (Object)null)
				{
					empressVoxelWorld.HostRequestCarve(_endPosition, EmpressVoxelLevelsPlugin.GunBreakRadius.Value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ParticleScriptExplosion), "Spawn")]
	internal static class EmpressVoxelExplosionPatch
	{
		private static void Postfix(Vector3 position, float size)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (EmpressVoxelLevelsPlugin.Enabled.Value && EmpressVoxelAccess.IsMasterClientOrSingleplayer())
			{
				EmpressVoxelWorld empressVoxelWorld = EmpressVoxelLevelsPlugin.World();
				if (!((Object)(object)empressVoxelWorld == (Object)null))
				{
					float radius = EmpressVoxelLevelsPlugin.ExplosionRadiusBase.Value + Mathf.Max(0f, size) * EmpressVoxelLevelsPlugin.ExplosionRadiusMultiplier.Value;
					empressVoxelWorld.HostRequestCarve(position, radius);
				}
			}
		}
	}
	public sealed class EmpressVoxelWorld : MonoBehaviour, IOnEventCallback
	{
		private struct Voxel
		{
			public GameObject Go;

			public bool Destructible;
		}

		private struct ClassifiedCell
		{
			public Vector3Int Cell;

			public bool IsFloor;

			public bool IsCeiling;

			public bool Destructible;
		}

		private struct FinalVoxel
		{
			public bool Destructible;

			public bool IsFloor;

			public bool IsCeiling;

			public bool Lifted;
		}

		private const byte CarveEventCode = 177;

		private const int DefaultLayer = 0;

		private const int DebrisLayer = 2;

		private const int CeilingScanRange = 14;

		private readonly Dictionary<Vector3Int, Voxel> _grid = new Dictionary<Vector3Int, Voxel>();

		private readonly RaycastHit[] _rayBuffer = (RaycastHit[])(object)new RaycastHit[16];

		private readonly Collider[] _overlapBuffer = (Collider[])(object)new Collider[64];

		private LevelGenerator _trackedGenerator;

		private bool _lastGenerated;

		private bool _building;

		private bool _ready;

		private GameObject _container;

		private Mesh _cubeMesh;

		private Material _voxelMaterial;

		private Vector3 _origin;

		private float _size = 1f;

		private int _debrisCount;

		private bool _photonRegistered;

		private void OnDisable()
		{
			UnregisterPhoton();
		}

		private void RegisterPhoton()
		{
			if (!_photonRegistered)
			{
				PhotonNetwork.AddCallbackTarget((object)this);
				_photonRegistered = true;
			}
		}

		private void UnregisterPhoton()
		{
			if (_photonRegistered)
			{
				PhotonNetwork.RemoveCallbackTarget((object)this);
				_photonRegistered = false;
			}
		}

		private void Update()
		{
			if (EmpressVoxelLevelsPlugin.Enabled == null)
			{
				return;
			}
			LevelGenerator val = EmpressVoxelAccess.LevelGeneratorInstance();
			if ((Object)(object)val != (Object)(object)_trackedGenerator)
			{
				ResetField();
				_trackedGenerator = val;
				_lastGenerated = false;
			}
			bool flag = (Object)(object)val != (Object)null && EmpressVoxelAccess.Generated(val);
			if (flag && !_lastGenerated && !_building)
			{
				ResetField();
				if (EmpressVoxelLevelsPlugin.Enabled.Value && ShouldVoxelizeCurrentLevel())
				{
					GameObject val2 = EmpressVoxelAccess.LevelParent(val);
					if ((Object)(object)val2 != (Object)null)
					{
						((MonoBehaviour)this).StartCoroutine(Build(val2));
					}
				}
			}
			else if (!flag && _lastGenerated)
			{
				ResetField();
			}
			_lastGenerated = flag;
		}

		private static bool ShouldVoxelizeCurrentLevel()
		{
			if (EmpressVoxelAccess.RunIsLevel())
			{
				return true;
			}
			if (EmpressVoxelLevelsPlugin.VoxelizeShop.Value && EmpressVoxelAccess.RunIsShop())
			{
				return true;
			}
			if (EmpressVoxelLevelsPlugin.VoxelizeLobby.Value)
			{
				return EmpressVoxelAccess.RunIsLobby();
			}
			return false;
		}

		internal void HostRequestCarve(Vector3 position, float radius)
		{
			//IL_0056: 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_0024: 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_002c: Expected O, but got Unknown
			//IL_0039: 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)
			if (_ready && !(radius <= 0f))
			{
				if (EmpressVoxelAccess.IsMultiplayer() && PhotonNetwork.InRoom)
				{
					RaiseEventOptions val = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					};
					PhotonNetwork.RaiseEvent((byte)177, (object)new object[2] { position, radius }, val, SendOptions.SendReliable);
				}
				DestroySphere(position, radius);
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code != 177 || !(photonEvent.CustomData is object[] array) || array.Length < 2)
			{
				return;
			}
			object obj = array[0];
			if (obj is Vector3)
			{
				Vector3 center = (Vector3)obj;
				obj = array[1];
				if (obj is float)
				{
					float radius = (float)obj;
					DestroySphere(center, radius);
				}
			}
		}

		private void DestroySphere(Vector3 center, float radius)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//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_007f: 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_00b3: 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_00b9: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (!_ready || _grid.Count == 0)
			{
				return;
			}
			Vector3Int val = WorldToCell(center - new Vector3(radius, radius, radius));
			Vector3Int val2 = WorldToCell(center + new Vector3(radius, radius, radius));
			float num = radius * radius;
			Vector3Int key = default(Vector3Int);
			for (int i = ((Vector3Int)(ref val)).x; i <= ((Vector3Int)(ref val2)).x; i++)
			{
				for (int j = ((Vector3Int)(ref val)).y; j <= ((Vector3Int)(ref val2)).y; j++)
				{
					for (int k = ((Vector3Int)(ref val)).z; k <= ((Vector3Int)(ref val2)).z; k++)
					{
						((Vector3Int)(ref key))..ctor(i, j, k);
						if (_grid.TryGetValue(key, out var value) && value.Destructible && !((Object)(object)value.Go == (Object)null))
						{
							Vector3 val3 = value.Go.transform.position - center;
							if (!(((Vector3)(ref val3)).sqrMagnitude > num))
							{
								SpawnDebris(value.Go.transform.position);
								Object.Destroy((Object)(object)value.Go);
								_grid.Remove(key);
							}
						}
					}
				}
			}
		}

		private IEnumerator Build(GameObject parent)
		{
			_building = true;
			_ready = false;
			if (EmpressVoxelAccess.IsMultiplayer() && PhotonNetwork.InRoom)
			{
				RegisterPhoton();
			}
			float size = (_size = Mathf.Clamp(EmpressVoxelLevelsPlugin.VoxelSize.Value, 0.5f, 4f));
			int budget = Mathf.Max(200, EmpressVoxelLevelsPlugin.BuildBudgetPerFrame.Value);
			int maxVoxels = EmpressVoxelLevelsPlugin.MaxVoxels.Value;
			List<Transform> roots = new List<Transform> { parent.transform };
			if (EmpressVoxelLevelsPlugin.VoxelizeStartRoom.Value)
			{
				StartRoom[] array = Object.FindObjectsOfType<StartRoom>();
				foreach (StartRoom val in array)
				{
					if ((Object)(object)val != (Object)null)
					{
						roots.Add(((Component)val).transform);
					}
				}
			}
			List<Collider> targets = new List<Collider>();
			Bounds val2 = default(Bounds);
			bool flag = false;
			foreach (Transform item in roots)
			{
				Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(true);
				foreach (Collider val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null) && !val3.isTrigger && val3.enabled && ((Component)val3).gameObject.layer == 0 && !IsProtectedObject(((Component)val3).gameObject))
					{
						targets.Add(val3);
						if (!flag)
						{
							val2 = val3.bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref val2)).Encapsulate(val3.bounds);
						}
					}
				}
			}
			if (!flag || targets.Count == 0)
			{
				_building = false;
				yield break;
			}
			_origin = ((Bounds)(ref val2)).min - new Vector3(size, size, size);
			EnsureSharedAssets();
			_container = new GameObject("EmpressVoxelContainer");
			HashSet<Collider> targetSet = new HashSet<Collider>(targets);
			HashSet<Vector3Int> occupancy = new HashSet<Vector3Int>();
			HashSet<Vector3Int> candidates = new HashSet<Vector3Int>();
			float cellVolume = size * size * size;
			float candidateCellCap = Mathf.Max((float)maxVoxels * 4f, 1000000f);
			int work = 0;
			foreach (Collider item2 in targets)
			{
				Bounds bounds = item2.bounds;
				((Bounds)(ref bounds)).Expand(size);
				Vector3 size2 = ((Bounds)(ref bounds)).size;
				if (size2.x * size2.y * size2.z / cellVolume > candidateCellCap)
				{
					continue;
				}
				Vector3Int cellMin = WorldToCell(((Bounds)(ref bounds)).min);
				Vector3Int cellMax = WorldToCell(((Bounds)(ref bounds)).max);
				for (int x6 = ((Vector3Int)(ref cellMin)).x; x6 <= ((Vector3Int)(ref cellMax)).x; x6++)
				{
					for (int y = ((Vector3Int)(ref cellMin)).y; y <= ((Vector3Int)(ref cellMax)).y; y++)
					{
						for (int z = ((Vector3Int)(ref cellMin)).z; z <= ((Vector3Int)(ref cellMax)).z; z++)
						{
							candidates.Add(new Vector3Int(x6, y, z));
							int i = work + 1;
							work = i;
							if (i >= budget)
							{
								work = 0;
								yield return null;
							}
						}
					}
				}
				cellMin = default(Vector3Int);
				cellMax = default(Vector3Int);
			}
			float num = size * Mathf.Clamp(EmpressVoxelLevelsPlugin.ProbeHorizontal.Value, 0.05f, 0.5f);
			float num2 = size * Mathf.Clamp(EmpressVoxelLevelsPlugin.ProbeVertical.Value, 0.05f, 0.5f);
			Vector3 probeExtents = new Vector3(num, num2, num);
			LayerMask probeMask = LayerMask.op_Implicit(1);
			foreach (Vector3Int item3 in candidates)
			{
				int num3 = Physics.OverlapBoxNonAlloc(CellCenter(item3), probeExtents, _overlapBuffer, Quaternion.identity, LayerMask.op_Implicit(probeMask), (QueryTriggerInteraction)1);
				for (int j = 0; j < num3; j++)
				{
					if (targetSet.Contains(_overlapBuffer[j]))
					{
						occupancy.Add(item3);
						break;
					}
				}
				int i = work + 1;
				work = i;
				if (i >= budget)
				{
					work = 0;
					yield return null;
				}
			}
			List<ClassifiedCell> classified = new List<ClassifiedCell>();
			HashSet<Vector3Int> rendered = new HashSet<Vector3Int>();
			foreach (Vector3Int item4 in occupancy)
			{
				Vector3Int current2 = item4;
				bool flag2 = !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y + 1, ((Vector3Int)(ref current2)).z));
				bool flag3 = !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y - 1, ((Vector3Int)(ref current2)).z));
				bool flag4 = !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x + 1, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z)) || !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x - 1, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z)) || !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z + 1)) || !occupancy.Contains(new Vector3Int(((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z - 1));
				if (flag2 || flag3 || flag4)
				{
					bool flag5 = flag2;
					bool flag6 = !flag2 && flag3;
					bool destructible = EmpressVoxelLevelsPlugin.EverythingDestructible.Value || (!flag5 && (!flag6 || !EmpressVoxelLevelsPlugin.ProtectCeilings.Value) && flag4);
					classified.Add(new ClassifiedCell
					{
						Cell = current2,
						IsFloor = flag5,
						IsCeiling = flag6,
						Destructible = destructible
					});
					rendered.Add(current2);
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
			}
			HashSet<Vector3Int> eroded = ErodeOpenings(classified, occupancy);
			bool alignFloors = EmpressVoxelLevelsPlugin.AlignFloorTops.Value;
			int raise = Mathf.Max(0, EmpressVoxelLevelsPlugin.CeilingRaise.Value);
			HashSet<Vector3Int> overhead = new HashSet<Vector3Int>();
			Vector3Int cell;
			if (raise > 0)
			{
				foreach (ClassifiedCell item5 in classified)
				{
					if (!eroded.Contains(item5.Cell))
					{
						cell = item5.Cell;
						int x7 = ((Vector3Int)(ref cell)).x;
						cell = item5.Cell;
						int num4 = ((Vector3Int)(ref cell)).y - 1;
						cell = item5.Cell;
						if (!occupancy.Contains(new Vector3Int(x7, num4, ((Vector3Int)(ref cell)).z)))
						{
							overhead.Add(item5.Cell);
						}
					}
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
			}
			HashSet<Vector3Int> raiseSet = new HashSet<Vector3Int>();
			foreach (Vector3Int item6 in overhead)
			{
				if (IsBroadSurface(overhead, item6) && HasFloorBelow(occupancy, item6) && IsTopmostCeiling(occupancy, item6))
				{
					raiseSet.Add(item6);
				}
				int i = work + 1;
				work = i;
				if (i >= budget)
				{
					work = 0;
					yield return null;
				}
			}
			Dictionary<Vector3Int, FinalVoxel> finalVoxels = new Dictionary<Vector3Int, FinalVoxel>();
			Vector3Int key = default(Vector3Int);
			foreach (ClassifiedCell item7 in classified)
			{
				if (!eroded.Contains(item7.Cell))
				{
					if (raiseSet.Contains(item7.Cell))
					{
						cell = item7.Cell;
						int x8 = ((Vector3Int)(ref cell)).x;
						cell = item7.Cell;
						int num5 = ((Vector3Int)(ref cell)).y + raise;
						cell = item7.Cell;
						((Vector3Int)(ref key))..ctor(x8, num5, ((Vector3Int)(ref cell)).z);
						finalVoxels[key] = new FinalVoxel
						{
							Destructible = item7.Destructible,
							IsFloor = false,
							IsCeiling = true,
							Lifted = true
						};
					}
					else
					{
						finalVoxels[item7.Cell] = new FinalVoxel
						{
							Destructible = item7.Destructible,
							IsFloor = item7.IsFloor,
							IsCeiling = item7.IsCeiling,
							Lifted = false
						};
					}
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
			}
			if (raise > 0)
			{
				Vector3Int key2 = default(Vector3Int);
				foreach (ClassifiedCell item8 in classified)
				{
					if (eroded.Contains(item8.Cell) || item8.IsFloor || item8.IsCeiling)
					{
						continue;
					}
					cell = item8.Cell;
					int x9 = ((Vector3Int)(ref cell)).x;
					cell = item8.Cell;
					int num6 = ((Vector3Int)(ref cell)).y + 1;
					cell = item8.Cell;
					if (!raiseSet.Contains(new Vector3Int(x9, num6, ((Vector3Int)(ref cell)).z)))
					{
						continue;
					}
					for (int k = 1; k <= raise; k++)
					{
						cell = item8.Cell;
						int x10 = ((Vector3Int)(ref cell)).x;
						cell = item8.Cell;
						int num7 = ((Vector3Int)(ref cell)).y + k;
						cell = item8.Cell;
						((Vector3Int)(ref key2))..ctor(x10, num7, ((Vector3Int)(ref cell)).z);
						if (!finalVoxels.ContainsKey(key2))
						{
							finalVoxels[key2] = new FinalVoxel
							{
								Destructible = item8.Destructible,
								IsFloor = false,
								IsCeiling = false,
								Lifted = true
							};
						}
					}
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
			}
			int spawned = 0;
			foreach (KeyValuePair<Vector3Int, FinalVoxel> item9 in finalVoxels)
			{
				Vector3Int key3 = item9.Key;
				FinalVoxel value = item9.Value;
				Vector3 val4 = CellCenter(key3);
				float surfaceY2;
				if (!value.Lifted && value.IsFloor && alignFloors && !rendered.Contains(new Vector3Int(((Vector3Int)(ref key3)).x, ((Vector3Int)(ref key3)).y - 1, ((Vector3Int)(ref key3)).z)))
				{
					if (TryFindSurface(new Vector3(val4.x, val4.y + size, val4.z), Vector3.down, size * 2f, probeMask, wantHighest: true, out var surfaceY))
					{
						val4.y = surfaceY - size * 0.5f;
					}
				}
				else if (!value.Lifted && value.IsCeiling && !rendered.Contains(new Vector3Int(((Vector3Int)(ref key3)).x, ((Vector3Int)(ref key3)).y + 1, ((Vector3Int)(ref key3)).z)) && TryFindSurface(new Vector3(val4.x, val4.y - size, val4.z), Vector3.up, size * 2f, probeMask, wantHighest: false, out surfaceY2))
				{
					val4.y = surfaceY2 + size * 0.5f;
				}
				CreateVoxel(key3, val4, value.Destructible);
				int i = spawned + 1;
				spawned = i;
				if (i >= maxVoxels)
				{
					EmpressVoxelLevelsPlugin.Log.LogWarning((object)$"Voxel cap of {maxVoxels} reached, remaining geometry left untouched.");
					break;
				}
				i = work + 1;
				work = i;
				if (i >= budget)
				{
					work = 0;
					yield return null;
				}
			}
			if (EmpressVoxelLevelsPlugin.HideOriginalRenderers.Value || EmpressVoxelLevelsPlugin.ReplaceColliders.Value)
			{
				foreach (Collider item10 in targets)
				{
					if (!((Object)(object)item10 == (Object)null))
					{
						if (EmpressVoxelLevelsPlugin.ReplaceColliders.Value)
						{
							item10.enabled = false;
						}
						int i = work + 1;
						work = i;
						if (i >= budget)
						{
							work = 0;
							yield return null;
						}
					}
				}
				if (EmpressVoxelLevelsPlugin.HideOriginalRenderers.Value)
				{
					foreach (Transform item11 in roots)
					{
						MeshRenderer[] componentsInChildren2 = ((Component)item11).GetComponentsInChildren<MeshRenderer>(true);
						foreach (MeshRenderer val5 in componentsInChildren2)
						{
							if (!((Object)(object)val5 == (Object)null) && ((Component)val5).gameObject.layer == 0 && !IsProtectedObject(((Component)val5).gameObject))
							{
								((Renderer)val5).enabled = false;
								int i = work + 1;
								work = i;
								if (i >= budget)
								{
									work = 0;
									yield return null;
								}
							}
						}
					}
				}
			}
			if (EmpressVoxelLevelsPlugin.RemoveDoors.Value)
			{
				foreach (Transform item12 in roots)
				{
					PhysGrabHinge[] componentsInChildren3 = ((Component)item12).GetComponentsInChildren<PhysGrabHinge>(true);
					foreach (PhysGrabHinge val6 in componentsInChildren3)
					{
						if (!((Object)(object)val6 == (Object)null) && !IsTruckOrShopFixture(((Component)val6).gameObject))
						{
							((Component)val6).gameObject.SetActive(false);
							int i = work + 1;
							work = i;
							if (i >= budget)
							{
								work = 0;
								yield return null;
							}
						}
					}
				}
			}
			if (EmpressVoxelLevelsPlugin.FreeTrappedLoot.Value)
			{
				ValuableObject[] array2 = Object.FindObjectsOfType<ValuableObject>();
				foreach (ValuableObject val7 in array2)
				{
					if ((Object)(object)val7 != (Object)null)
					{
						CarveAroundObject(((Component)val7).gameObject, 0f);
					}
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
				PhysGrabObject[] array3 = Object.FindObjectsOfType<PhysGrabObject>();
				foreach (PhysGrabObject val8 in array3)
				{
					if ((Object)(object)val8 != (Object)null)
					{
						CarveAroundObject(((Component)val8).gameObject, 0f);
					}
					int i = work + 1;
					work = i;
					if (i >= budget)
					{
						work = 0;
						yield return null;
					}
				}
			}
			TruckScreenText[] array4 = Object.FindObjectsOfType<TruckScreenText>();
			foreach (TruckScreenText val9 in array4)
			{
				if ((Object)(object)val9 != (Object)null)
				{
					CarveAroundObject(((Component)val9).gameObject, _size);
				}
				int i = work + 1;
				work = i;
				if (i >= budget)
				{
					work = 0;
					yield return null;
				}
			}
			_ready = true;
			_building = false;
			EmpressVoxelLevelsPlugin.Log.LogInfo((object)$"Voxelized level with {spawned} surface voxels at {_size}m resolution.");
		}

		private HashSet<Vector3Int> ErodeOpenings(List<ClassifiedCell> classified, HashSet<Vector3Int> occupancy)
		{
			//IL_003b: 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_0081: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Vector3Int> hashSet = new HashSet<Vector3Int>();
			int value = EmpressVoxelLevelsPlugin.OpeningWiden.Value;
			if (value <= 0)
			{
				return hashSet;
			}
			List<Vector3Int> list = new List<Vector3Int>();
			foreach (ClassifiedCell item in classified)
			{
				if (!item.IsFloor)
				{
					list.Add(item.Cell);
				}
			}
			for (int i = 0; i < value; i++)
			{
				List<Vector3Int> list2 = new List<Vector3Int>();
				foreach (Vector3Int item2 in list)
				{
					Vector3Int current2 = item2;
					if (!hashSet.Contains(current2))
					{
						bool flag = IsSolid(occupancy, hashSet, ((Vector3Int)(ref current2)).x + 1, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z);
						bool flag2 = IsSolid(occupancy, hashSet, ((Vector3Int)(ref current2)).x - 1, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z);
						bool flag3 = IsSolid(occupancy, hashSet, ((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z + 1);
						bool flag4 = IsSolid(occupancy, hashSet, ((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y, ((Vector3Int)(ref current2)).z - 1);
						bool flag5 = IsSolid(occupancy, hashSet, ((Vector3Int)(ref current2)).x, ((Vector3Int)(ref current2)).y - 1, ((Vector3Int)(ref current2)).z);
						int num = ((!flag) ? 1 : 0) + ((!flag2) ? 1 : 0) + ((!flag3) ? 1 : 0) + ((!flag4) ? 1 : 0);
						bool flag6 = !flag && !flag2 && flag3 && flag4;
						bool flag7 = !flag3 && !flag4 && flag && flag2;
						bool num2 = num >= 2 && !flag6 && !flag7;
						bool flag8 = !flag5 && (flag6 || flag7);
						if (num2 || flag8)
						{
							list2.Add(current2);
						}
					}
				}
				if (list2.Count == 0)
				{
					break;
				}
				foreach (Vector3Int item3 in list2)
				{
					hashSet.Add(item3);
				}
			}
			return hashSet;
		}

		private static bool IsSolid(HashSet<Vector3Int> occupancy, HashSet<Vector3Int> eroded, int x, int y, int z)
		{
			//IL_000c: 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)
			Vector3Int item = default(Vector3Int);
			((Vector3Int)(ref item))..ctor(x, y, z);
			if (occupancy.Contains(item))
			{
				return !eroded.Contains(item);
			}
			return false;
		}

		private static bool IsBroadSurface(HashSet<Vector3Int> overhead, Vector3Int cell)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			int num = 0;
			if (overhead.Contains(new Vector3Int(((Vector3Int)(ref cell)).x + 1, ((Vector3Int)(ref cell)).y, ((Vector3Int)(ref cell)).z)))
			{
				num++;
			}
			if (overhead.Contains(new Vector3Int(((Vector3Int)(ref cell)).x - 1, ((Vector3Int)(ref cell)).y, ((Vector3Int)(ref cell)).z)))
			{
				num++;
			}
			if (overhead.Contains(new Vector3Int(((Vector3Int)(ref cell)).x, ((Vector3Int)(ref cell)).y, ((Vector3Int)(ref cell)).z + 1)))
			{
				num++;
			}
			if (overhead.Contains(new Vector3Int(((Vector3Int)(ref cell)).x, ((Vector3Int)(ref cell)).y, ((Vector3Int)(ref cell)).z - 1)))
			{
				num++;
			}
			return num >= 3;
		}

		private static bool HasFloorBelow(HashSet<Vector3Int> occupancy, Vector3Int cell)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 1; i <= 14; i++)
			{
				if (occupancy.Contains(new Vector3Int(((Vector3Int)(ref cell)).x, ((Vector3Int)(ref cell)).y - i, ((Vector3Int)(ref cell)).z)))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsTopmostCeiling(HashSet<Vector3Int> occupancy, Vector3Int cell)
		{
			//IL_002d: 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)
			int i;
			for (i = ((Vector3Int)(ref cell)).y; i - ((Vector3Int)(ref cell)).y < 14 && occupancy.Contains(new Vector3Int(((Vector3Int)(ref cell)).x, i + 1, ((Vector3Int)(ref cell)).z)); i++)
			{
			}
			for (int j = 1; j <= 14; j++)
			{
				if (occupancy.Contains(new Vector3Int(((Vector3Int)(ref cell)).x, i + j, ((Vector3Int)(ref cell)).z)))
				{
					return false;
				}
			}
			return true;
		}

		private void CarveAroundObject(GameObject go, float padding)
		{
			//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_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_0054: 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_0063: 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_00ad: 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)
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(true);
			Vector3Int val4 = default(Vector3Int);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled)
				{
					continue;
				}
				Bounds bounds = val.bounds;
				if (padding > 0f)
				{
					((Bounds)(ref bounds)).Expand(padding * 2f);
				}
				Vector3Int val2 = WorldToCell(((Bounds)(ref bounds)).min);
				Vector3Int val3 = WorldToCell(((Bounds)(ref bounds)).max);
				for (int j = ((Vector3Int)(ref val2)).x; j <= ((Vector3Int)(ref val3)).x; j++)
				{
					for (int k = ((Vector3Int)(ref val2)).y; k <= ((Vector3Int)(ref val3)).y; k++)
					{
						for (int l = ((Vector3Int)(ref val2)).z; l <= ((Vector3Int)(ref val3)).z; l++)
						{
							((Vector3Int)(ref val4))..ctor(j, k, l);
							if (((Bounds)(ref bounds)).Contains(CellCenter(val4)) && _grid.TryGetValue(val4, out var value))
							{
								if ((Object)(object)value.Go != (Object)null)
								{
									Object.Destroy((Object)(object)value.Go);
								}
								_grid.Remove(val4);
							}
						}
					}
				}
			}
		}

		private static bool IsProtectedObject(GameObject go)
		{
			if (!((Object)(object)go.GetComponentInParent<ExtractionPoint>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ChargingStation>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<TruckHealer>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<PhysGrabObject>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<PhysGrabHinge>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ValuableObject>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ItemAttributes>(true) != (Object)null))
			{
				return IsTruckOrShopFixture(go);
			}
			return true;
		}

		private static bool IsTruckOrShopFixture(GameObject go)
		{
			if (!((Object)(object)go.GetComponentInParent<TruckDoor>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<TruckScreenText>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ShopManager>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ShopKeeper>(true) != (Object)null) && !((Object)(object)go.GetComponentInParent<ShopKeycardDoor>(true) != (Object)null))
			{
				return (Object)(object)go.GetComponentInParent<CosmeticShopMachine>(true) != (Object)null;
			}
			return true;
		}

		private bool TryFindSurface(Vector3 origin, Vector3 direction, float distance, LayerMask mask, bool wantHighest, out float surfaceY)
		{
			//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_0011: 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)
			surfaceY = 0f;
			int num = Physics.RaycastNonAlloc(origin, direction, _rayBuffer, distance, LayerMask.op_Implicit(mask), (QueryTriggerInteraction)1);
			bool flag = false;
			for (int i = 0; i < num; i++)
			{
				Collider collider = ((RaycastHit)(ref _rayBuffer[i])).collider;
				if (!((Object)(object)collider == (Object)null) && !collider.isTrigger && !IsProtectedObject(((Component)collider).gameObject))
				{
					float y = ((RaycastHit)(ref _rayBuffer[i])).point.y;
					if (!flag || (wantHighest ? (y > surfaceY) : (y < surfaceY)))
					{
						surfaceY = y;
						flag = true;
					}
				}
			}
			return flag;
		}

		private void CreateVoxel(Vector3Int cell, Vector3 position, bool destructible)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_002f: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//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_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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Voxel")
			{
				layer = 0
			};
			val.transform.SetParent(_container.transform, true);
			val.transform.position = position;
			val.transform.localScale = Vector3.one;
			val.AddComponent<MeshFilter>().sharedMesh = _cubeMesh;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = _voxelMaterial;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			MaterialPropertyBlock val2 = new MaterialPropertyBlock();
			Color val3 = TintForCell(cell, destructible);
			val2.SetColor("_BaseColor", val3);
			val2.SetColor("_Color", val3);
			((Renderer)obj).SetPropertyBlock(val2);
			if (EmpressVoxelLevelsPlugin.ReplaceColliders.Value)
			{
				val.AddComponent<BoxCollider>().size = Vector3.one * _size;
			}
			_grid[cell] = new Voxel
			{
				Go = val,
				Destructible = destructible
			};
		}

		private void SpawnDebris(Vector3 position)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0037: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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)
			if (EmpressVoxelLevelsPlugin.DebrisEnabled.Value && _debrisCount < EmpressVoxelLevelsPlugin.MaxDebris.Value)
			{
				GameObject val = new GameObject("VoxelDebris")
				{
					layer = 2
				};
				val.transform.position = position;
				val.transform.localScale = Vector3.one * 0.45f;
				val.AddComponent<MeshFilter>().sharedMesh = _cubeMesh;
				MeshRenderer obj = val.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = _voxelMaterial;
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				Color val3 = TintForCell(WorldToCell(position), destructible: true);
				val2.SetColor("_BaseColor", val3);
				val2.SetColor("_Color", val3);
				((Renderer)obj).SetPropertyBlock(val2);
				val.AddComponent<BoxCollider>().size = Vector3.one * _size;
				Rigidbody obj2 = val.AddComponent<Rigidbody>();
				obj2.mass = 0.4f;
				Vector3 val4 = default(Vector3);
				((Vector3)(ref val4))..ctor(Random.Range(-1.6f, 1.6f), Random.Range(1.5f, 3.5f), Random.Range(-1.6f, 1.6f));
				obj2.AddForce(val4, (ForceMode)1);
				obj2.AddTorque(Random.insideUnitSphere * 2f, (ForceMode)1);
				_debrisCount++;
				((MonoBehaviour)this).StartCoroutine(DespawnDebris(val, EmpressVoxelLevelsPlugin.DebrisLifetime.Value));
			}
		}

		private IEnumerator DespawnDebris(GameObject go, float lifetime)
		{
			yield return (object)new WaitForSeconds(lifetime);
			if ((Object)(object)go != (Object)null)
			{
				Object.Destroy((Object)(object)go);
			}
			_debrisCount = Mathf.Max(0, _debrisCount - 1);
		}

		private Color TintForCell(Vector3Int cell, bool destructible)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			float num = Mathf.Abs(Mathf.Sin((float)((Vector3Int)(ref cell)).x * 12.9898f + (float)((Vector3Int)(ref cell)).y * 78.233f + (float)((Vector3Int)(ref cell)).z * 37.719f) * 43758.547f);
			num -= Mathf.Floor(num);
			float num2 = Mathf.Lerp(0.34f, 0.52f, num);
			Color val = default(Color);
			((Color)(ref val))..ctor(num2, num2 * 0.99f, num2 * 0.94f, 1f);
			if (destructible)
			{
				val = Color.Lerp(val, new Color(0.55f, 0.45f, 0.38f, 1f), 0.25f);
				return val;
			}
			return val;
		}

		private void EnsureSharedAssets()
		{
			//IL_0064: 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_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_0088: Expected O, but got Unknown
			if ((Object)(object)_cubeMesh == (Object)null)
			{
				_cubeMesh = BuildCubeMesh(_size);
			}
			if ((Object)(object)_voxelMaterial == (Object)null)
			{
				Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Sprites/Default");
				_voxelMaterial = new Material(val)
				{
					name = "EmpressVoxelMaterial",
					enableInstancing = true,
					hideFlags = (HideFlags)61
				};
			}
		}

		private static Mesh BuildCubeMesh(float size)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0088: 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_011a: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: 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_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			float num = size * 0.5f;
			Vector3[] array = (Vector3[])(object)new Vector3[8]
			{
				new Vector3(0f - num, 0f - num, 0f - num),
				new Vector3(num, 0f - num, 0f - num),
				new Vector3(num, 0f - num, num),
				new Vector3(0f - num, 0f - num, num),
				new Vector3(0f - num, num, 0f - num),
				new Vector3(num, num, 0f - num),
				new Vector3(num, num, num),
				new Vector3(0f - num, num, num)
			};
			int[][] array2 = new int[6][]
			{
				new int[4] { 0, 1, 2, 3 },
				new int[4] { 7, 6, 5, 4 },
				new int[4] { 4, 5, 1, 0 },
				new int[4] { 6, 7, 3, 2 },
				new int[4] { 5, 6, 2, 1 },
				new int[4] { 7, 4, 0, 3 }
			};
			Vector3[] array3 = (Vector3[])(object)new Vector3[6]
			{
				Vector3.down,
				Vector3.up,
				Vector3.back,
				Vector3.forward,
				Vector3.right,
				Vector3.left
			};
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < array2.Length; i++)
			{
				int count = list.Count;
				int[] array4 = array2[i];
				foreach (int num2 in array4)
				{
					list.Add(array[num2]);
					list2.Add(array3[i]);
				}
				list3.Add(count);
				list3.Add(count + 1);
				list3.Add(count + 2);
				list3.Add(count);
				list3.Add(count + 2);
				list3.Add(count + 3);
			}
			Mesh val = new Mesh
			{
				name = "EmpressVoxelCube",
				hideFlags = (HideFlags)61
			};
			val.SetVertices(list);
			val.SetNormals(list2);
			val.SetTriangles(list3, 0);
			val.RecalculateBounds();
			return val;
		}

		private void ResetField()
		{
			((MonoBehaviour)this).StopAllCoroutines();
			UnregisterPhoton();
			_building = false;
			_ready = false;
			_debrisCount = 0;
			_grid.Clear();
			if ((Object)(object)_container != (Object)null)
			{
				Object.Destroy((Object)(object)_container);
				_container = null;
			}
		}

		private Vector3Int WorldToCell(Vector3 point)
		{
			//IL_0000: 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_003c: 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)
			return new Vector3Int(Mathf.FloorToInt((point.x - _origin.x) / _size), Mathf.FloorToInt((point.y - _origin.y) / _size), Mathf.FloorToInt((point.z - _origin.z) / _size));
		}

		private Vector3 CellCenter(Vector3Int cell)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(_origin.x + ((float)((Vector3Int)(ref cell)).x + 0.5f) * _size, _origin.y + ((float)((Vector3Int)(ref cell)).y + 0.5f) * _size, _origin.z + ((float)((Vector3Int)(ref cell)).z + 0.5f) * _size);
		}
	}
}