Decompiled source of HomeBubble v0.2.1

HomeBubble.dll

Decompiled 5 days ago
using System;
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 HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("HomeBubble")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Keep enemies out of your base with a protective bubble.")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+b91b46aabe10cf64f2dc83d4fd51b1b75fa36a94")]
[assembly: AssemblyProduct("HomeBubble")]
[assembly: AssemblyTitle("HomeBubble")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HomeBubble
{
	[HarmonyPatch(typeof(EffectArea), "IsPointInsideNoMonsterArea")]
	internal static class InsideNoMonsterPatch
	{
		private static void Postfix(Vector3 p, ref EffectArea __result)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__result == (Object)null)
			{
				__result = HomeBubbleZone.FindInside(p);
			}
		}
	}
	[HarmonyPatch(typeof(EffectArea), "IsPointCloseToNoMonsterArea")]
	internal static class CloseToNoMonsterPatch
	{
		private static void Postfix(Vector3 p, ref EffectArea __result)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__result == (Object)null)
			{
				__result = HomeBubbleZone.FindClose(p);
			}
		}
	}
	[HarmonyPatch(typeof(ShieldDomeImageEffect), "SetShieldData")]
	internal static class HideVanillaDomePatch
	{
		private static bool Prefix(ShieldGenerator shield)
		{
			return !HomeBubbleZone.UsesForceField(shield);
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class PlacementGhostPatch
	{
		private static void Postfix(Player __instance)
		{
			//IL_001f: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = __instance.m_placementGhost;
			if (!((Object)(object)placementGhost == (Object)null) && !((Object)(object)placementGhost.GetComponent<HomeBubbleZone>() == (Object)null) && (int)__instance.m_placementStatus == 0 && !HomeBubbleZone.TryFindStations(placementGhost.transform.position, out var _, out var _))
			{
				__instance.m_placementStatus = (PlacementStatus)7;
				__instance.SetPlacementGhostValid(false);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	internal static class PlacementMessagePatch
	{
		private static void Postfix(Player __instance, bool __result)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = __instance.m_placementGhost;
			if (!__result && !((Object)(object)placementGhost == (Object)null) && !((Object)(object)placementGhost.GetComponent<HomeBubbleZone>() == (Object)null) && (int)__instance.m_placementStatus == 7 && !HomeBubbleZone.TryFindStations(placementGhost.transform.position, out var _, out var problem))
			{
				((Character)__instance).Message((MessageType)2, problem, 0, (Sprite)null, false);
			}
		}
	}
	[HarmonyPatch(typeof(ShieldGenerator), "OnAddFuel")]
	internal static class AddFuelPatch
	{
		private static bool Prefix(ShieldGenerator __instance, Humanoid user, ref bool __result)
		{
			HomeBubbleZone componentInParent = ((Component)__instance).GetComponentInParent<HomeBubbleZone>();
			if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsCollapsed(out var stationLabels))
			{
				return true;
			}
			((Character)user).Message((MessageType)2, CollapseText.For(stationLabels), 0, (Sprite)null, false);
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(ShieldGenerator), "OnHoverAddFuel")]
	internal static class HoverFuelPatch
	{
		private static void Postfix(ShieldGenerator __instance, ref string __result)
		{
			HomeBubbleZone componentInParent = ((Component)__instance).GetComponentInParent<HomeBubbleZone>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			if (componentInParent.IsCollapsed(out var stationLabels))
			{
				__result = "Home Bubble\n<color=red>" + CollapseText.For(stationLabels) + "</color>";
				return;
			}
			string text = (componentInParent.IsOff ? "Turn on" : "Turn off");
			__result = __result + "\n[<color=yellow><b>Shift + E</b></color>] " + text;
			if (componentInParent.IsOff)
			{
				__result += "\n<color=red>Switched off</color>";
			}
		}
	}
	[HarmonyPatch(typeof(ShieldGenerator), "UpdateShield")]
	internal static class GeneratorOffPatch
	{
		private static void Postfix(ShieldGenerator __instance)
		{
			((Component)__instance).GetComponentInParent<HomeBubbleZone>()?.ApplyGeneratorState();
		}
	}
	[HarmonyPatch(typeof(Switch), "Interact")]
	internal static class ToggleBubblePatch
	{
		private static bool Prefix(Switch __instance, bool hold, bool alt, ref bool __result)
		{
			if (!alt)
			{
				return true;
			}
			HomeBubbleZone componentInParent = ((Component)__instance).GetComponentInParent<HomeBubbleZone>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return true;
			}
			if (!hold)
			{
				componentInParent.Toggle();
			}
			__result = false;
			return false;
		}
	}
	internal static class CollapseText
	{
		public static string For(string station)
		{
			return "The bubble is down because its " + station + " was destroyed. Rebuild it nearby to bring the bubble back.";
		}
	}
	internal static class BubblePrefab
	{
		public const string PrefabName = "HB_HomeBubble";

		private const string VanillaGenerator = "piece_shieldgenerator";

		private const string TraderLocation = "Vendor_BlackForest";

		public const string ForceFieldName = "HB_ForceField";

		private static GameObject _prefab;

		public static void Register()
		{
			//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_007e: 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_00b3: Expected O, but got Unknown
			//IL_00f3: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0114: 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_0124: 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_0133: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_shieldgenerator");
			if ((Object)(object)prefab == (Object)null)
			{
				HomeBubblePlugin.Log.LogError((object)"Vanilla prefab not found: piece_shieldgenerator");
				return;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("HB_HomeBubble", prefab);
			ShieldGenerator componentInChildren = val.GetComponentInChildren<ShieldGenerator>(true);
			componentInChildren.m_enableAttack = false;
			componentInChildren.m_maxFuel = BubbleConfig.MaxFuel.Value;
			componentInChildren.m_name = "Home Bubble";
			GameObject val2 = new GameObject("HB_Area");
			val2.transform.SetParent(val.transform, false);
			SphereCollider obj = val2.AddComponent<SphereCollider>();
			obj.radius = 0.1f;
			((Collider)obj).isTrigger = true;
			val2.AddComponent<EffectArea>().m_type = (Type)0;
			val.AddComponent<HomeBubbleZone>();
			_prefab = val;
			PieceConfig val3 = new PieceConfig();
			val3.Name = "Home Bubble";
			val3.Description = "A protective bubble for your base. Monsters keep out, but you can still build inside. Needs a Workbench, Forge, Stonecutter and Artisan Table nearby, and grows as they are upgraded. Fuelled by bones.";
			val3.PieceTable = "Hammer";
			val3.Category = "Defence";
			val3.CraftingStation = "";
			val3.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig
				{
					Item = "Iron",
					Amount = 5,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Copper",
					Amount = 5,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "DragonTear",
					Amount = 2,
					Recover = true
				}
			};
			PieceConfig val4 = val3;
			PieceManager.Instance.AddPiece(new CustomPiece(val, false, val4));
			HomeBubblePlugin.Log.LogInfo((object)"Registered HB_HomeBubble");
		}

		public static void AttachForceField()
		{
			//IL_00d4: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			ZoneManager.OnVanillaLocationsAvailable -= AttachForceField;
			if ((Object)(object)_prefab == (Object)null)
			{
				return;
			}
			try
			{
				GameObject val = ZoneManager.Instance.GetZoneLocation("Vendor_BlackForest")?.m_prefab.Asset ?? PrefabManager.Instance.GetPrefab("Vendor_BlackForest");
				Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("ForceField") : null);
				if ((Object)(object)val2 == (Object)null)
				{
					HomeBubblePlugin.Log.LogWarning((object)(((Object)(object)val == (Object)null) ? "The trader's camp prefab was not found; the bubble keeps the shield generator's dome." : "The trader's camp has no ForceField object; the bubble keeps the shield generator's dome."));
					return;
				}
				GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject, _prefab.transform);
				((Object)obj).name = "HB_ForceField";
				obj.transform.localPosition = Vector3.zero;
				obj.transform.localRotation = Quaternion.identity;
				obj.transform.localScale = Vector3.one;
				BoostVisibility(obj);
				EffectArea[] componentsInChildren = obj.GetComponentsInChildren<EffectArea>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)((Component)componentsInChildren[i]).gameObject);
				}
			}
			catch (Exception ex)
			{
				HomeBubblePlugin.Log.LogError((object)("Failed to attach the trader's force field: " + ex));
			}
		}

		private static Color ParseTint()
		{
			//IL_0028: 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)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(BubbleConfig.Tint.Value, ref result))
			{
				return new Color(0.3f, 0.72f, 1f);
			}
			return result;
		}

		private static void BoostVisibility(GameObject field)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0040: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//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_0061: 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)
			Color val = ParseTint();
			MeshRenderer component = field.GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				Material[] array = (Material[])(object)new Material[((Renderer)component).sharedMaterials.Length];
				for (int i = 0; i < array.Length; i++)
				{
					Material val2 = new Material(((Renderer)component).sharedMaterials[i]);
					if (val2.HasProperty("_Color"))
					{
						val2.SetColor("_Color", new Color(val.r, val.g, val.b, 1f));
					}
					if (val2.HasProperty("_RefractionIntensity"))
					{
						val2.SetFloat("_RefractionIntensity", val2.GetFloat("_RefractionIntensity") * BubbleConfig.Visibility.Value);
					}
					array[i] = val2;
				}
				((Renderer)component).sharedMaterials = array;
			}
			Shader val3 = Shader.Find("Sprites/Default");
			MeshFilter component2 = field.GetComponent<MeshFilter>();
			float value = BubbleConfig.TintOpacity.Value;
			if ((Object)(object)val3 != (Object)null && (Object)(object)component2 != (Object)null && value > 0f)
			{
				GameObject val4 = new GameObject("HB_Shell");
				val4.transform.SetParent(field.transform, false);
				val4.AddComponent<MeshFilter>().sharedMesh = component2.sharedMesh;
				MeshRenderer obj = val4.AddComponent<MeshRenderer>();
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
				((Renderer)obj).sharedMaterial = new Material(val3)
				{
					color = new Color(val.r, val.g, val.b, value)
				};
			}
		}
	}
	internal class HomeBubbleZone : MonoBehaviour
	{
		private const string RadiusKey = "HB_radius";

		private const string BrokenKey = "HB_broken";

		private const int MissChecksBeforeCollapse = 5;

		private const float CollapsedRadius = 0.2f;

		private const string DrainTimeKey = "HB_lastDrain";

		private const float DrainInterval = 10f;

		private const string OffKey = "HB_off";

		private const float FadeSpeed = 0.5f;

		private const float LowFuelOpacity = 0.25f;

		private static readonly Color LowFuelColor = new Color(1f, 0.15f, 0.1f);

		private const float NoMonsterCloseMargin = 15f;

		private static readonly string[] StationKeys = new string[4] { "HB_station0", "HB_station1", "HB_station2", "HB_station3" };

		private static readonly (string Prefab, string Label)[] RequiredStations = new(string, string)[4]
		{
			("piece_workbench", "Workbench"),
			("forge", "Forge"),
			("piece_stonecutter", "Stonecutter"),
			("piece_artisanstation", "Artisan Table")
		};

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

		public static readonly List<HomeBubbleZone> Instances = new List<HomeBubbleZone>();

		private ZNetView _nview;

		private ShieldGenerator _shield;

		private EffectArea _area;

		private Transform _field;

		private float _fieldUnitRadius = 0.5f;

		private bool _collapsed;

		private float _timer = 10f;

		private float _drainTimer;

		private readonly int[] _missChecks = new int[4];

		private Material[] _fieldMaterials = (Material[])(object)new Material[0];

		private Color[] _fieldColors;

		private float[] _fieldRefraction;

		private Material _shellMaterial;

		private Color _shellColor;

		private float _shownFuel = -1f;

		private float _appliedFuel = -1f;

		private bool _off;

		private float _lowFuelLoopStart;

		private readonly List<Behaviour> _silenced = new List<Behaviour>();

		private readonly List<ParticleSystem> _stopped = new List<ParticleSystem>();

		public bool IsOff => _off;

		private void Start()
		{
			//IL_011e: 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_00c1: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (Player.IsPlacementGhost(((Component)this).gameObject))
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_nview = ((Component)this).GetComponent<ZNetView>();
			_shield = ((Component)this).GetComponentInChildren<ShieldGenerator>(true);
			_area = ((Component)this).GetComponentInChildren<EffectArea>(true);
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || (Object)(object)_shield == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_field = ((Component)this).transform.Find("HB_ForceField");
			MeshFilter val = (Object.op_Implicit((Object)(object)_field) ? ((Component)_field).GetComponent<MeshFilter>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
			{
				Bounds bounds = val.sharedMesh.bounds;
				_fieldUnitRadius = Mathf.Max(0.01f, ((Bounds)(ref bounds)).extents.x);
			}
			_lowFuelLoopStart = _shield.m_shieldLowLoopFuelStart;
			SetUpFieldLook();
			Instances.Add(this);
			if (_nview.IsOwner() && _nview.GetZDO().GetZDOID(StationKeys[0]) == ZDOID.None)
			{
				ClaimStations();
			}
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
			Material[] fieldMaterials = _fieldMaterials;
			for (int i = 0; i < fieldMaterials.Length; i++)
			{
				Object.Destroy((Object)(object)fieldMaterials[i]);
			}
			if ((Object)(object)_shellMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_shellMaterial);
			}
		}

		private void SetUpFieldLook()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_field == (Object)null)
			{
				return;
			}
			MeshRenderer component = ((Component)_field).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				_fieldMaterials = ((Renderer)component).materials;
				_fieldColors = (Color[])(object)new Color[_fieldMaterials.Length];
				_fieldRefraction = new float[_fieldMaterials.Length];
				for (int i = 0; i < _fieldMaterials.Length; i++)
				{
					Material val = _fieldMaterials[i];
					_fieldColors[i] = (val.HasProperty("_Color") ? val.GetColor("_Color") : Color.white);
					_fieldRefraction[i] = (val.HasProperty("_RefractionIntensity") ? val.GetFloat("_RefractionIntensity") : 0f);
				}
			}
			Transform val2 = _field.Find("HB_Shell");
			MeshRenderer val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<MeshRenderer>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				_shellMaterial = ((Renderer)val3).material;
				_shellColor = _shellMaterial.color;
			}
		}

		private void ApplyFuelLook(float fuel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0039: 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_0064: 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_00af: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			Color lowFuelColor = LowFuelColor;
			float num = Mathf.Lerp(0.25f, 1f, fuel);
			for (int i = 0; i < _fieldMaterials.Length; i++)
			{
				Material val = _fieldMaterials[i];
				if (val.HasProperty("_Color"))
				{
					Color val2 = Color.Lerp(lowFuelColor, _fieldColors[i], fuel);
					val2.a = _fieldColors[i].a;
					val.SetColor("_Color", val2);
				}
				if (val.HasProperty("_RefractionIntensity"))
				{
					val.SetFloat("_RefractionIntensity", _fieldRefraction[i] * num);
				}
			}
			if ((Object)(object)_shellMaterial != (Object)null)
			{
				Color color = Color.Lerp(lowFuelColor, _shellColor, fuel);
				color.a = _shellColor.a * num;
				_shellMaterial.color = color;
			}
		}

		public void ApplyGeneratorState()
		{
			//IL_0050: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_shield == (Object)null)
			{
				return;
			}
			_shield.m_shieldLowLoopFuelStart = (_off ? 0f : _lowFuelLoopStart);
			if (_off)
			{
				Character.SetupContinuousEffect(((Component)_shield).transform, ((Component)_shield).transform.position, false, _shield.m_shieldLowLoop, ref _shield.m_lowLoopInstances, default(ZDOID));
				GameObject enabledObject = _shield.m_enabledObject;
				if (enabledObject != null)
				{
					enabledObject.SetActive(false);
				}
				GameObject disabledObject = _shield.m_disabledObject;
				if (disabledObject != null)
				{
					disabledObject.SetActive(true);
				}
				Behaviour[] componentsInChildren = ((Component)this).GetComponentsInChildren<Behaviour>(true);
				foreach (Behaviour val in componentsInChildren)
				{
					if ((val is Light || val is AudioSource) && val.enabled)
					{
						val.enabled = false;
						_silenced.Add(val);
					}
				}
				ParticleSystem[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val2 in componentsInChildren2)
				{
					if (val2.isPlaying)
					{
						val2.Stop(true, (ParticleSystemStopBehavior)0);
						_stopped.Add(val2);
					}
				}
			}
			else
			{
				if (_silenced.Count <= 0 && _stopped.Count <= 0)
				{
					return;
				}
				foreach (Behaviour item in _silenced)
				{
					if ((Object)(object)item != (Object)null)
					{
						item.enabled = true;
					}
				}
				foreach (ParticleSystem item2 in _stopped)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						item2.Play(true);
					}
				}
				_silenced.Clear();
				_stopped.Clear();
				((MonoBehaviour)_shield).Invoke("UpdateShield", 0f);
			}
		}

		public void Toggle()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				_nview.ClaimOwnership();
				ZDO zDO = _nview.GetZDO();
				bool flag = !zDO.GetBool("HB_off", false);
				zDO.Set("HB_off", flag);
				_off = flag;
				_timer = 10f;
				ApplyGeneratorState();
			}
		}

		public static bool UsesForceField(ShieldGenerator shield)
		{
			HomeBubbleZone componentInParent = ((Component)shield).GetComponentInParent<HomeBubbleZone>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return (Object)(object)componentInParent._field != (Object)null;
			}
			return false;
		}

		private void LateUpdate()
		{
			//IL_0103: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_field == (Object)null || (Object)(object)_shield == (Object)null || (Object)(object)_shield.m_shieldDome == (Object)null)
			{
				return;
			}
			float radius = _shield.m_radius;
			bool flag = radius > 0.1f && !_collapsed && !_off;
			if (((Component)_field).gameObject.activeSelf != flag)
			{
				((Component)_field).gameObject.SetActive(flag);
			}
			if (flag)
			{
				float fuelRatio = _shield.GetFuelRatio();
				if (_shownFuel < 0f)
				{
					_shownFuel = fuelRatio;
				}
				else
				{
					_shownFuel = Mathf.MoveTowards(_shownFuel, fuelRatio, 0.5f * Time.deltaTime);
				}
				if (!Mathf.Approximately(_shownFuel, _appliedFuel))
				{
					_appliedFuel = _shownFuel;
					ApplyFuelLook(_shownFuel);
				}
				_field.position = _shield.m_shieldDome.transform.position;
				_field.localScale = Vector3.one * (radius / _fieldUnitRadius);
			}
		}

		private void Update()
		{
			_drainTimer += Time.deltaTime;
			_timer += Time.deltaTime;
			if (_timer < 1f || !_nview.IsValid())
			{
				return;
			}
			_timer = 0f;
			ZDO zDO = _nview.GetZDO();
			if (_nview.IsOwner())
			{
				CheckStationsStillStand(zDO);
			}
			_off = zDO.GetBool("HB_off", false);
			_collapsed = IsCollapsed(out var _);
			if (_collapsed || _off)
			{
				_shield.m_minShieldRadius = 0.2f;
				_shield.m_maxShieldRadius = 0.2f;
				return;
			}
			if (_nview.IsOwner())
			{
				float? num = ComputeRadius(zDO);
				if (num.HasValue)
				{
					zDO.Set("HB_radius", num.Value);
				}
				if (_drainTimer >= 10f)
				{
					_drainTimer = 0f;
					DrainFuel(zDO);
				}
			}
			float num2 = zDO.GetFloat("HB_radius", BubbleConfig.BaseRadius.Value);
			_shield.m_minShieldRadius = num2;
			_shield.m_maxShieldRadius = num2;
		}

		public bool IsCollapsed(out string stationLabels)
		{
			int num = (((Object)(object)_nview != (Object)null && _nview.IsValid()) ? _nview.GetZDO().GetInt("HB_broken", 0) : 0);
			List<string> list = new List<string>();
			for (int i = 0; i < RequiredStations.Length; i++)
			{
				if ((num & (1 << i)) != 0)
				{
					list.Add(RequiredStations[i].Label);
				}
			}
			stationLabels = string.Join(" and ", list);
			return num != 0;
		}

		private void CheckStationsStillStand(ZDO zdo)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_00b1: 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)
			int num = zdo.GetInt("HB_broken", 0);
			int num2 = num;
			for (int i = 0; i < StationKeys.Length; i++)
			{
				ZDOID zDOID = zdo.GetZDOID(StationKeys[i]);
				if (!(zDOID == ZDOID.None))
				{
					bool flag = (Object)(object)ZNetScene.instance.FindInstance(zDOID) == (Object)null && ZDOMan.instance.GetZDO(zDOID) == null;
					_missChecks[i] = (flag ? (_missChecks[i] + 1) : 0);
					if (_missChecks[i] >= 5)
					{
						num2 |= 1 << i;
					}
				}
			}
			if (num2 != 0)
			{
				HashSet<ZDOID> claimed = ClaimedStations();
				for (int j = 0; j < StationKeys.Length; j++)
				{
					if ((num2 & (1 << j)) != 0)
					{
						CraftingStation val = FindUnclaimedStation(j, ((Component)this).transform.position, claimed);
						if ((Object)(object)val != (Object)null)
						{
							zdo.Set(StationKeys[j], ((Component)val).GetComponent<ZNetView>().GetZDO().m_uid);
							num2 &= ~(1 << j);
							_missChecks[j] = 0;
						}
					}
				}
			}
			if (num2 != num)
			{
				zdo.Set("HB_broken", num2);
			}
		}

		private void DrainFuel(ZDO zdo)
		{
			long ticks = ZNet.instance.GetTime().Ticks;
			long num = zdo.GetLong("HB_lastDrain", 0L);
			zdo.Set("HB_lastDrain", ticks);
			float value = BubbleConfig.MinutesPerBone.Value;
			if (num > 0 && !(value <= 0f))
			{
				float fuel = _shield.GetFuel();
				if (!(fuel <= 0f))
				{
					double totalMinutes = new TimeSpan(ticks - num).TotalMinutes;
					_shield.SetFuel(Mathf.Max(0f, fuel - (float)(totalMinutes / (double)value)));
				}
			}
		}

		private void ClaimStations()
		{
			//IL_0006: 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)
			if (TryFindStations(((Component)this).transform.position, out var found, out var _))
			{
				ZDO zDO = _nview.GetZDO();
				for (int i = 0; i < found.Length; i++)
				{
					zDO.Set(StationKeys[i], ((Component)found[i]).GetComponent<ZNetView>().GetZDO().m_uid);
				}
			}
		}

		private float? ComputeRadius(ZDO zdo)
		{
			//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < StationKeys.Length; i++)
			{
				ZDOID zDOID = zdo.GetZDOID(StationKeys[i]);
				GameObject val = ((zDOID == ZDOID.None) ? null : ZNetScene.instance.FindInstance(zDOID));
				CraftingStation val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<CraftingStation>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return null;
				}
				num += CountUpgrades(val2);
				num2 += CountAvailableUpgrades(val2);
			}
			float num3 = ((num2 > 0) ? Mathf.Clamp01((float)num / (float)num2) : 0f);
			return Mathf.Lerp(BubbleConfig.BaseRadius.Value, BubbleConfig.FullRadius.Value, num3);
		}

		private static int CountUpgrades(CraftingStation station)
		{
			//IL_0050: 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)
			HashSet<string> hashSet = new HashSet<string>();
			foreach (StationExtension allExtension in StationExtension.m_allExtensions)
			{
				if ((Object)(object)allExtension != (Object)null && (Object)(object)allExtension.m_craftingStation != (Object)null && allExtension.m_craftingStation.m_name == station.m_name && Vector3.Distance(((Component)allExtension).transform.position, ((Component)station).transform.position) < allExtension.m_maxStationDistance)
				{
					hashSet.Add(Utils.GetPrefabName(((Component)allExtension).gameObject));
				}
			}
			return hashSet.Count;
		}

		private static int CountAvailableUpgrades(CraftingStation station)
		{
			if (!MaxUpgrades.TryGetValue(station.m_name, out var value))
			{
				HashSet<string> hashSet = new HashSet<string>();
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					StationExtension val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<StationExtension>() : null);
					if ((Object)(object)val != (Object)null && (Object)(object)val.m_craftingStation != (Object)null && val.m_craftingStation.m_name == station.m_name)
					{
						hashSet.Add(((Object)prefab).name);
					}
				}
				value = hashSet.Count;
				MaxUpgrades[station.m_name] = value;
			}
			return value;
		}

		private bool Protects(Vector3 point, float margin)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (_collapsed || _off || (Object)(object)_shield == (Object)null || (Object)(object)_shield.m_shieldDome == (Object)null)
			{
				return false;
			}
			float radius = _shield.m_radius;
			if (radius > 0.1f)
			{
				return Vector3.Distance(_shield.m_shieldDome.transform.position, point) < radius + margin;
			}
			return false;
		}

		public static EffectArea FindInside(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Find(point, 0f);
		}

		public static EffectArea FindClose(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Find(point, 15f);
		}

		private static EffectArea Find(Vector3 point, float margin)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			foreach (HomeBubbleZone instance in Instances)
			{
				if ((Object)(object)instance != (Object)null && instance.Protects(point, margin))
				{
					return instance._area;
				}
			}
			return null;
		}

		private static HashSet<ZDOID> ClaimedStations()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			foreach (HomeBubbleZone instance in Instances)
			{
				if (!((Object)(object)instance == (Object)null) && instance._nview.IsValid())
				{
					string[] stationKeys = StationKeys;
					foreach (string text in stationKeys)
					{
						hashSet.Add(instance._nview.GetZDO().GetZDOID(text));
					}
				}
			}
			return hashSet;
		}

		private static CraftingStation FindUnclaimedStation(int index, Vector3 point, HashSet<ZDOID> claimed)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			bool anyInRange;
			return FindUnclaimedStation(index, point, claimed, out anyInRange);
		}

		private static CraftingStation FindUnclaimedStation(int index, Vector3 point, HashSet<ZDOID> claimed, out bool anyInRange)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			anyInRange = false;
			CraftingStation result = null;
			float num = float.MaxValue;
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if ((Object)(object)allStation == (Object)null || Utils.GetPrefabName(((Component)allStation).gameObject) != RequiredStations[index].Prefab)
				{
					continue;
				}
				Vector3 val = point;
				val.y = ((Component)allStation).transform.position.y;
				float num2 = Vector3.Distance(((Component)allStation).transform.position, val);
				if (!(num2 >= allStation.GetStationBuildRange()))
				{
					anyInRange = true;
					ZNetView component = ((Component)allStation).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid() && !claimed.Contains(component.GetZDO().m_uid) && num2 < num)
					{
						num = num2;
						result = allStation;
					}
				}
			}
			return result;
		}

		public static bool TryFindStations(Vector3 point, out CraftingStation[] found, out string problem)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ZDOID> claimed = ClaimedStations();
			found = (CraftingStation[])(object)new CraftingStation[RequiredStations.Length];
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			for (int i = 0; i < RequiredStations.Length; i++)
			{
				found[i] = FindUnclaimedStation(i, point, claimed, out var anyInRange);
				if ((Object)(object)found[i] == (Object)null)
				{
					(anyInRange ? list2 : list).Add(RequiredStations[i].Label);
				}
			}
			if (list.Count == 0 && list2.Count == 0)
			{
				problem = null;
				return true;
			}
			problem = ((list.Count > 0) ? ("Home Bubble needs these in range: " + string.Join(", ", list)) : ("Already covered by another Home Bubble: " + string.Join(", ", list2)));
			return false;
		}
	}
	[BepInPlugin("javidahmed64592.homebubble", "Home Bubble", "0.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class HomeBubblePlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "javidahmed64592.homebubble";

		public const string PluginName = "Home Bubble";

		public const string PluginVersion = "0.2.1";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BubbleConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("javidahmed64592.homebubble");
			_harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefabs;
			ZoneManager.OnVanillaLocationsAvailable += BubblePrefab.AttachForceField;
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void RegisterPrefabs()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefabs;
			try
			{
				BubblePrefab.Register();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to register the Home Bubble prefab: " + ex));
			}
		}
	}
	internal static class BubbleConfig
	{
		public static ConfigEntry<float> BaseRadius;

		public static ConfigEntry<float> FullRadius;

		public static ConfigEntry<float> MinutesPerBone;

		public static ConfigEntry<int> MaxFuel;

		public static ConfigEntry<float> Visibility;

		public static ConfigEntry<string> Tint;

		public static ConfigEntry<float> TintOpacity;

		public static void Bind(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			BaseRadius = config.Bind<float>("Bubble", "BaseRadius", 24f, new ConfigDescription("Radius (metres) of a bubble whose crafting stations have no upgrades.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
			FullRadius = config.Bind<float>("Bubble", "FullRadius", 48f, new ConfigDescription("Radius (metres) once every upgrade is built on the bubble's crafting stations.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
			MinutesPerBone = config.Bind<float>("Bubble", "MinutesPerBone", 30f, new ConfigDescription("Real-time minutes one bone keeps the bubble up. 0 means bones are only used up by projectile hits.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
			MaxFuel = config.Bind<int>("Bubble", "MaxFuel", 50, new ConfigDescription("The most bones the generator can hold. Takes effect after a restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			Visibility = config.Bind<float>("Look", "Distortion", 4f, new ConfigDescription("How strongly the bubble warps what you see through it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>()));
			Tint = config.Bind<string>("Look", "Tint", "#4DB8FF", "Colour of the bubble as a hex code, e.g. #4DB8FF.");
			TintOpacity = config.Bind<float>("Look", "TintOpacity", 0.06f, new ConfigDescription("How solid the bubble's coloured surface is. 0 turns it off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.6f), Array.Empty<object>()));
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}