Decompiled source of Power Elec v0.1.4

BepInEx/plugins/PowerElec/PowerElec.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using PowerElec.Art;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyInformationalVersion("0.1.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.4.0")]
namespace PowerElec
{
	[BepInPlugin("powerelec.valheim.power", "Power Elec", "0.1.4")]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class PowerElecPlugin : BaseUnityPlugin
	{
		public const string Id = "powerelec.valheim.power";

		public const string Version = "0.1.4";

		public const string HammerName = "PowerElec_Hammer";

		public const string TableName = "_PowerElec_PieceTable";

		internal static PowerElecPlugin Instance;

		internal ConfigEntry<float> Range;

		internal ConfigEntry<float> MinimumOutput;

		internal ConfigEntry<float> HeatRadius;

		internal ConfigEntry<float> LampBrightness;

		internal ConfigEntry<float> LampReach;

		internal ConfigEntry<int> DefaultLampBrightness;

		private bool registered;

		internal static bool Headless => (int)SystemInfo.graphicsDeviceType == 4;

		internal static long Now
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return 0L;
				}
				return ZNet.instance.GetTime().Ticks;
			}
		}

		private void Awake()
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0148: 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_0155: Expected O, but got Unknown
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			Instance = this;
			Range = Setting("DistributionRadius", 60f, 10f, 120f, "Supply radius in metres, measured in 3D from turbine base. Default 60m is a new baseline. Nearby source and consumers must be loaded.");
			MinimumOutput = Setting("MinimumOutput", 0.02f, 0f, 0.9f, "Output (0..1) must exceed this value to supply power. Native wind and obstruction determine turbine output.");
			HeatRadius = Setting("HeaterRadius", 6f, 1f, 12f, "Radius of the heater's native warmth effect in metres. No burning damage, fuel or smoke.");
			LampBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Lighting", "LampBrightnessMultiplier", 1f, new ConfigDescription("Legacy setting used only to migrate the default brightness for lamps without a saved percentage. Use DefaultLampBrightnessPercent for defaults, or press E at a lamp to adjust it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			DefaultLampBrightness = ((BaseUnityPlugin)this).Config.Bind<int>("Lighting", "DefaultLampBrightnessPercent", LampPolicy.FromLegacy(LampBrightness.Value), new ConfigDescription("Default brightness for lamps without a saved setting, from 20 to 100 percent of the original 0.1.2 lamp intensity. 60 preserves the 0.1.3 baseline. Each lamp can be adjusted in game. Heater excluded.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 100), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			LampReach = ((BaseUnityPlugin)this).Config.Bind<float>("Lighting", "LampRangeMultiplier", 1f, new ConfigDescription("Light reach multiplier for pendant, garden and wall lamps only. Does not change electrical supply radius or the heater.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			AddTranslations();
			if (!Headless)
			{
				((Component)this).gameObject.AddComponent<LampSettingsUI>();
			}
			PrefabManager.OnVanillaPrefabsAvailable += Register;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Power Elec 0.1.4 loading: electrical hammer, turbine, pendant lamp, garden lamp, wall lamp and smokeless heater.");
		}

		private ConfigEntry<float> Setting(string key, float value, float min, float max, string description)
		{
			//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_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>("Electricity", key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private void AddTranslations()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string[,] array = new string[19, 3]
			{
				{ "pe_hammer", "Power Elec Hammer", "ค\u0e49อน Power Elec" },
				{ "pe_hammer_desc", "A black iron and copper tool for electrical construction. Equip it and open the build menu.", "ค\u0e49อนเหล\u0e47กดำแต\u0e48งทองแดงสำหร\u0e31บสร\u0e49างระบบไฟฟ\u0e49า ถ\u0e37อค\u0e49อนแล\u0e49วเป\u0e34ดเมน\u0e39ก\u0e48อสร\u0e49าง" },
				{ "pe_turbine", "Power Elec Wind Turbine", "Power Elec ก\u0e31งห\u0e31นผล\u0e34ตไฟฟ\u0e49า" },
				{ "pe_turbine_desc", "Produces electricity from wind. Supply nearby Power Elec lamps and heaters automatically. Keep its sails clear of obstructions.", "ผล\u0e34ตไฟฟ\u0e49าจากลม จ\u0e48ายไฟให\u0e49โคมไฟและเตาในระยะอ\u0e31ตโนม\u0e31ต\u0e34 ควรวางในท\u0e35\u0e48โล\u0e48ง" },
				{ "pe_pendant", "Power Elec Pendant Lamp", "Power Elec โคมไฟแขวน" },
				{ "pe_pendant_desc", "Warm copper pendant light. Requires a working turbine in range. No fuel or switch.", "โคมไฟแขวนทองแดงแสงอ\u0e38\u0e48น ร\u0e31บไฟจากก\u0e31งห\u0e31นในระยะ ไม\u0e48ใช\u0e49เช\u0e37\u0e49อเพล\u0e34งหร\u0e37อสว\u0e34ตช\u0e4c" },
				{ "pe_garden", "Power Elec Garden Lamp", "Power Elec โคมไฟสวน" },
				{ "pe_garden_desc", "Black timber garden post with a warm copper lantern. Requires a working turbine in range.", "เสาไม\u0e49ดำพร\u0e49อมโคมทองแดงแสงอ\u0e38\u0e48น ร\u0e31บไฟจากก\u0e31งห\u0e31นในระยะ" },
				{ "pe_wall", "Power Elec Wall Lamp", "Power Elec โคมไฟต\u0e34ดผน\u0e31ง" },
				{ "pe_wall_desc", "A copper wall lantern with a forged bracket. Requires a working turbine in range.", "โคมต\u0e34ดผน\u0e31งทองแดงพร\u0e49อมขาย\u0e36ดเหล\u0e47ก ร\u0e31บไฟจากก\u0e31งห\u0e31นในระยะ" },
				{ "pe_heater", "Power Elec Heater", "Power Elec เตาให\u0e49ความร\u0e49อน" },
				{ "pe_heater_desc", "Smokeless electric warmth. Provides native near-fire warmth while powered; normal shelter and Resting rules still apply.", "เตาไฟฟ\u0e49าไร\u0e49คว\u0e31น ให\u0e49ความอ\u0e38\u0e48นเม\u0e37\u0e48อม\u0e35ไฟฟ\u0e49า การพ\u0e31กผ\u0e48อนย\u0e31งใช\u0e49เง\u0e37\u0e48อนไขหล\u0e31งคาและท\u0e35\u0e48กำบ\u0e31งตามเกม" },
				{ "pe_on", "Power connected", "ม\u0e35ไฟฟ\u0e49า" },
				{ "pe_off", "No power: place a turbine nearby in open wind", "ไม\u0e48ม\u0e35ไฟฟ\u0e49า: วางก\u0e31งห\u0e31นในระยะและในท\u0e35\u0e48โล\u0e48ง" },
				{ "pe_output", "Wind output", "กำล\u0e31งผล\u0e34ตจากลม" },
				{ "pe_range", "Supply radius", "ร\u0e31ศม\u0e35จ\u0e48ายไฟ" },
				{ "pe_wait", "Waiting for power update", "กำล\u0e31งรอข\u0e49อม\u0e39ลไฟฟ\u0e49า" },
				{ "pe_brightness", "Brightness", "Brightness" },
				{ "pe_adjust", "Adjust brightness", "Adjust brightness" }
			};
			for (int i = 0; i < array.GetLength(0); i++)
			{
				string text = "English";
				localization.AddTranslation(ref text, ref array[i, 0], array[i, 1]);
				text = "Thai";
				localization.AddTranslation(ref text, ref array[i, 0], array[i, 2]);
			}
			LampVariant[] array2 = LampVariants.Added();
			foreach (LampVariant lampVariant in array2)
			{
				string text2 = ((lampVariant.Tint == 1) ? "Blue" : "Green");
				string text3 = ((lampVariant.Kind == 0) ? "Pendant Lamp" : ((lampVariant.Kind == 1) ? "Garden Lamp" : "Wall Lamp"));
				string[] array3 = new string[2] { "English", "Thai" };
				for (int k = 0; k < array3.Length; k++)
				{
					string text4 = array3[k];
					localization.AddTranslation(ref text4, ref lampVariant.Token, "Power Elec " + text2 + " " + text3);
					string text = lampVariant.Token + "_desc";
					localization.AddTranslation(ref text4, ref text, text2 + " light in the matching copper lantern housing. Requires turbine power. Press E to adjust this lamp from 20 to 100 percent.");
				}
			}
		}

		internal static GameObject Prefab(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				throw new InvalidOperationException("Required vanilla prefab not found: " + name);
			}
			return prefab;
		}

		private void Register()
		{
			if (registered)
			{
				return;
			}
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			try
			{
				string[] array = new string[14]
				{
					"Hammer", "windmill", "wood_pole", "piece_dvergr_lantern_pole", "piece_workbench", "forge", "Wood", "RoundLog", "Stone", "Copper",
					"SurtlingCore", "Resin", "GreydwarfEye", "Guck"
				};
				for (int i = 0; i < array.Length; i++)
				{
					Prefab(array[i]);
				}
				Models.Initialize();
				RegisterHammer();
				RegisterTurbine();
				RegisterAppliance("PowerElec_Pendant", "pe_pendant", Models.BuildPendant, 0, Cost("Wood", 2), Cost("Copper", 1), Cost("Resin", 2));
				RegisterAppliance("PowerElec_GardenLamp", "pe_garden", Models.BuildGarden, 1, Cost("RoundLog", 2), Cost("Copper", 1), Cost("Resin", 2));
				RegisterAppliance("PowerElec_Heater", "pe_heater", Models.BuildHeater, 2, Cost("Stone", 10), Cost("Copper", 5), Cost("SurtlingCore", 1));
				RegisterAppliance("PowerElec_WallLamp", "pe_wall", Models.BuildWall, 3, Cost("Wood", 2), Cost("Copper", 1), Cost("Resin", 2));
				LampVariant[] array2 = LampVariants.Added();
				foreach (LampVariant variant in array2)
				{
					RegisterApplianceInternal(variant.Name, variant.Token, (GameObject go) => Models.BuildColored(go, variant.Kind, variant.Tint), variant.Kind, variant.Tint, Cost(variant.BaseItem, 2), Cost("Copper", 1), Cost(variant.ColorItem, 2));
				}
				registered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Power Elec ready: separate hammer, turbine, nine adjustable lamps and unchanged heater registered.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Power Elec registration failed. Do not save a modded world until fixed: " + ex));
			}
		}

		private void RegisterHammer()
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			CustomPieceTable val = new CustomPieceTable("_PowerElec_PieceTable", new PieceTableConfig
			{
				CanRemovePieces = true,
				GuessUsage = false
			});
			if (!PieceManager.Instance.AddPieceTable(val))
			{
				throw new InvalidOperationException("Electrical build table registration failed.");
			}
			ItemDrop component = Prefab("Hammer").GetComponent<ItemDrop>();
			GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("PowerElec_Hammer", ((Component)component).gameObject);
			RequireInactive(val2);
			ItemDrop component2 = val2.GetComponent<ItemDrop>();
			component2.m_itemData = component.m_itemData.Clone();
			SharedData val3 = new SharedData();
			FieldInfo[] fields = typeof(SharedData).GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val3, fieldInfo.GetValue(component.m_itemData.m_shared));
			}
			component2.m_itemData.m_shared = val3;
			component2.m_itemData.m_dropPrefab = val2;
			val3.m_name = "$pe_hammer";
			val3.m_description = "$pe_hammer_desc";
			val3.m_buildPieces = val.PieceTable;
			val3.m_maxQuality = 1;
			val3.m_maxDurability = 200f;
			val3.m_durabilityPerLevel = 0f;
			val3.m_weight = 2f;
			if (!Headless)
			{
				val3.m_icons = (Sprite[])(object)new Sprite[1] { Models.Icon("hammer", component.m_itemData.GetIcon()) };
			}
			component2.m_itemData.m_durability = val3.m_maxDurability;
			Models.BuildHammer(val2);
			ItemConfig val4 = new ItemConfig
			{
				Amount = 1,
				CraftingStation = "forge",
				RepairStation = "forge",
				MinStationLevel = 1
			};
			val4.AddRequirement("Wood", 5, 0);
			val4.AddRequirement("Copper", 2, 0);
			val4.AddRequirement("SurtlingCore", 1, 0);
			if (!ItemManager.Instance.AddItem(new CustomItem(val2, false, val4)))
			{
				throw new InvalidOperationException("Electrical hammer registration failed.");
			}
		}

		private static void RequireInactive(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go) || go.activeInHierarchy)
			{
				throw new InvalidOperationException("Prefab must be configured inside the inactive prefab container.");
			}
		}

		private static Requirement Cost(string item, int amount)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = Prefab(item).GetComponent<ItemDrop>(),
				m_amount = amount,
				m_recover = true
			};
		}

		private void ConfigurePiece(GameObject go, string token, string icon, params Requirement[] resources)
		{
			//IL_0053: 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)
			RequireInactive(go);
			Piece component = go.GetComponent<Piece>();
			component.m_name = "$" + token;
			component.m_description = "$" + token + "_desc";
			component.m_resources = resources;
			component.m_craftingStation = Prefab("piece_workbench").GetComponent<CraftingStation>();
			component.m_usage = (UsageTagFlags)2;
			component.m_enabled = true;
			component.m_isUpgrade = false;
			component.m_comfort = 0;
			component.m_comfortObject = null;
			component.m_canBeRemoved = true;
			component.m_onlyInBiome = (Biome)0;
			if (!Headless)
			{
				component.m_icon = Models.Icon(icon, component.m_icon);
			}
			go.GetComponent<ZNetView>().m_persistent = true;
		}

		private void RegisterCustomPiece(GameObject go)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			Models.SetRenderedIcon(go);
			CustomPiece val = new CustomPiece(go, "_PowerElec_PieceTable", false);
			val.Usage = new string[1] { "Crafting" };
			CustomPiece val2 = val;
			if (!PieceManager.Instance.AddPiece(val2))
			{
				throw new InvalidOperationException("Piece registration failed: " + ((Object)go).name);
			}
		}

		private void RegisterTurbine()
		{
			Windmill component = Prefab("windmill").GetComponent<Windmill>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				throw new InvalidOperationException("Native Windmill settings missing.");
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("PowerElec_WindTurbine", Prefab("wood_pole"));
			ConfigurePiece(val, "pe_turbine", "turbine", Cost("RoundLog", 20), Cost("Stone", 20), Cost("Copper", 5), Cost("SurtlingCore", 2));
			Models.ClearPiece(val);
			val.GetComponent<Piece>().m_noInWater = true;
			GameObject model = Models.BuildTurbine(val, component);
			ConfigureWear(val, model, 1500f, supports: true);
			val.AddComponent<WindGenerator>();
			RegisterCustomPiece(val);
		}

		private static void ConfigureWear(GameObject go, GameObject model, float health, bool supports)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			WearNTear component = go.GetComponent<WearNTear>();
			component.m_new = (component.m_worn = (component.m_broken = model));
			component.m_wet = null;
			component.m_snow = (component.m_snowWorn = (component.m_snowBroken = null));
			component.m_noRoofWear = false;
			component.m_noSupportWear = false;
			component.m_supports = supports;
			component.m_burnable = false;
			component.m_materialType = (MaterialType)2;
			component.m_health = health;
			component.m_fragmentRoots = (GameObject[])(object)new GameObject[1] { model };
			component.m_nonSolidRenderers = new List<Renderer>();
		}

		private void RegisterAppliance(string name, string token, Func<GameObject, GameObject> build, int type, params Requirement[] costs)
		{
			RegisterApplianceInternal(name, token, build, type, 0, costs);
		}

		private void RegisterApplianceInternal(string name, string token, Func<GameObject, GameObject> build, int type, int tint, params Requirement[] costs)
		{
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(name, Prefab("wood_pole"));
			ConfigurePiece(val, token, type switch
			{
				3 => "wall", 
				1 => "garden", 
				0 => "pendant", 
				_ => "heater", 
			}, costs);
			Models.ClearPiece(val);
			if (!Headless && tint != 0)
			{
				val.GetComponent<Piece>().m_icon = Models.Icon(type switch
				{
					1 => "garden", 
					0 => "pendant", 
					_ => "wall", 
				} + ((tint == 1) ? "_blue" : "_green"), val.GetComponent<Piece>().m_icon);
			}
			Piece component = val.GetComponent<Piece>();
			component.m_groundPiece = false;
			component.m_groundOnly = false;
			component.m_notOnFloor = false;
			component.m_notOnWood = false;
			component.m_noInWater = true;
			component.m_waterPiece = false;
			component.m_inCeilingOnly = false;
			component.m_spaceRequirement = 0f;
			GameObject model = build(val);
			if (type != 2)
			{
				val.AddComponent<LampSettings>();
			}
			ConfigureWear(val, model, (type == 2) ? 800f : 300f, supports: false);
			val.AddComponent<ElectricAppliance>().Configure(type, tint);
			RegisterCustomPiece(val);
		}

		internal static void LogModelInfo(string message)
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogError(string context, Exception e)
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)(context + ": " + e));
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			Instance = null;
		}
	}
	public sealed class WindGenerator : MonoBehaviour, Hoverable
	{
		private const string OutputKey = "pe_output_v1";

		private const string TickKey = "pe_output_tick_v1";

		private static readonly HashSet<WindGenerator> Active = new HashSet<WindGenerator>();

		private ZNetView view;

		private Windmill wind;

		private float nextTick;

		private bool faulted;

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			wind = ((Component)this).GetComponent<Windmill>();
			nextTick = Time.time + 1f;
		}

		private void OnEnable()
		{
			Active.Add(this);
		}

		private void OnDisable()
		{
			Active.Remove(this);
		}

		private void OnDestroy()
		{
			Active.Remove(this);
		}

		private void Update()
		{
			if (Time.time < nextTick)
			{
				return;
			}
			nextTick = Time.time + 2f;
			if (!Object.op_Implicit((Object)(object)view) || !PowerRules.CanWrite(view.IsValid(), view.IsOwner()))
			{
				return;
			}
			long now = PowerElecPlugin.Now;
			if (now <= 0)
			{
				return;
			}
			try
			{
				float num = ((Object.op_Implicit((Object)(object)wind) && Object.op_Implicit((Object)(object)EnvMan.instance)) ? PowerRules.SanitizeOutput(wind.GetPowerOutput()) : 0f);
				view.GetZDO().Set("pe_output_v1", num);
				view.GetZDO().Set("pe_output_tick_v1", now);
			}
			catch (Exception e)
			{
				view.GetZDO().Set("pe_output_v1", 0f);
				if (!faulted)
				{
					faulted = true;
					PowerElecPlugin.LogError("Generator power sampling failed", e);
				}
			}
		}

		internal SupplySnapshot Snapshot()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			SupplySnapshot result = new SupplySnapshot
			{
				X = position.x,
				Y = position.y,
				Z = position.z
			};
			if (!Object.op_Implicit((Object)(object)this) || !((Behaviour)this).isActiveAndEnabled || !Object.op_Implicit((Object)(object)view) || !view.IsValid())
			{
				return result;
			}
			ZDO zDO = view.GetZDO();
			result.Valid = true;
			result.Output = zDO.GetFloat("pe_output_v1", 0f);
			result.Updated = zDO.GetLong("pe_output_tick_v1", 0L);
			return result;
		}

		internal static bool Supplies(Vector3 position, long now)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)PowerElecPlugin.Instance))
			{
				return false;
			}
			float value = PowerElecPlugin.Instance.Range.Value;
			float value2 = PowerElecPlugin.Instance.MinimumOutput.Value;
			foreach (WindGenerator item in Active)
			{
				if (Object.op_Implicit((Object)(object)item) && PowerRules.CanSupply(item.Snapshot(), position.x, position.y, position.z, value, value2, now))
				{
					return true;
				}
			}
			return false;
		}

		public string GetHoverName()
		{
			return Localization.instance.Localize("$pe_turbine");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			SupplySnapshot supplySnapshot = Snapshot();
			float num = (Object.op_Implicit((Object)(object)PowerElecPlugin.Instance) ? PowerElecPlugin.Instance.Range.Value : 60f);
			string text = (PowerRules.Fresh(PowerElecPlugin.Now, supplySnapshot.Updated) ? (Math.Round(supplySnapshot.Output * 100f) + "%") : "$pe_wait");
			return Localization.instance.Localize("$pe_turbine\n$pe_output: " + text + "\n$pe_range: " + num.ToString("0") + " m");
		}
	}
	public sealed class ElectricAppliance : MonoBehaviour, Hoverable, Interactable
	{
		private const string PowerKey = "pe_powered_v1";

		private const string TickKey = "pe_power_tick_v1";

		[SerializeField]
		private int kind;

		[SerializeField]
		private int tint;

		private ZNetView view;

		private GameObject glow;

		private GameObject heat;

		private SphereCollider heatCollider;

		private RoomLighting roomLighting;

		private LampSettings settings;

		private float nextTick;

		private bool faulted;

		internal void Configure(int value, int color = 0)
		{
			kind = value;
			tint = color;
		}

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			Transform val = ((Component)this).transform.Find("PowerElecModel/PoweredGlow");
			Transform val2 = ((Component)this).transform.Find("PowerElecModel/PoweredHeat");
			glow = (Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : null);
			heat = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).gameObject : null);
			if (Object.op_Implicit((Object)(object)heat))
			{
				heatCollider = heat.GetComponent<SphereCollider>();
			}
			roomLighting = ((Component)this).GetComponentInChildren<RoomLighting>(true);
			settings = ((Component)this).GetComponent<LampSettings>();
			SetEffects(on: false);
			nextTick = Time.time + 0.5f;
		}

		private void Update()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < nextTick)
			{
				return;
			}
			nextTick = Time.time + 1f;
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
			{
				SetEffects(on: false);
				return;
			}
			try
			{
				long now = PowerElecPlugin.Now;
				ZDO zDO = view.GetZDO();
				if (PowerRules.CanWrite(view.IsValid(), view.IsOwner()) && now > 0)
				{
					zDO.Set("pe_powered_v1", WindGenerator.Supplies(((Component)this).transform.position, now));
					zDO.Set("pe_power_tick_v1", now);
				}
				if (Object.op_Implicit((Object)(object)heatCollider) && Object.op_Implicit((Object)(object)PowerElecPlugin.Instance))
				{
					heatCollider.radius = PowerElecPlugin.Instance.HeatRadius.Value;
				}
				SetEffects(PowerRules.ConsumerOn(zDO.GetBool("pe_powered_v1", false), now, zDO.GetLong("pe_power_tick_v1", 0L)));
			}
			catch (Exception e)
			{
				SetEffects(on: false);
				if (!faulted)
				{
					faulted = true;
					PowerElecPlugin.LogError("Appliance power update failed", e);
				}
			}
		}

		private void SetEffects(bool on)
		{
			if (Object.op_Implicit((Object)(object)roomLighting))
			{
				roomLighting.SetPowered(on, Object.op_Implicit((Object)(object)settings) ? settings.Percent : 60);
			}
			if (Object.op_Implicit((Object)(object)glow) && glow.activeSelf != on)
			{
				glow.SetActive(on);
			}
			if (Object.op_Implicit((Object)(object)heat) && heat.activeSelf != on)
			{
				heat.SetActive(on);
			}
		}

		private void OnDisable()
		{
			SetEffects(on: false);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (!hold && Object.op_Implicit((Object)(object)settings) && user is Player)
			{
				return settings.Open((Player)user);
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetHoverName()
		{
			return Localization.instance.Localize("$" + LampVariants.Token(kind, tint));
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			bool flag = Object.op_Implicit((Object)(object)view) && view.IsValid() && PowerRules.ConsumerOn(view.GetZDO().GetBool("pe_powered_v1", false), PowerElecPlugin.Now, view.GetZDO().GetLong("pe_power_tick_v1", 0L));
			string text = GetHoverName() + "\n" + Localization.instance.Localize(flag ? "$pe_on" : "$pe_off");
			if (Object.op_Implicit((Object)(object)settings))
			{
				text = text + "\n" + Localization.instance.Localize("$pe_brightness") + ": " + settings.Percent + "%\n" + Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] $pe_adjust");
			}
			return text;
		}
	}
	internal struct SupplySnapshot
	{
		internal bool Valid;

		internal float X;

		internal float Y;

		internal float Z;

		internal float Output;

		internal long Updated;
	}
	internal static class PowerRules
	{
		internal const double FreshSeconds = 8.0;

		internal static bool Finite(float v)
		{
			if (!float.IsNaN(v))
			{
				return !float.IsInfinity(v);
			}
			return false;
		}

		internal static bool Fresh(long now, long updated)
		{
			if (now <= 0 || updated <= 0)
			{
				return false;
			}
			double num = ((double)now - (double)updated) / 10000000.0;
			if (num >= -2.0)
			{
				return num <= 8.0;
			}
			return false;
		}

		internal static bool CanWrite(bool valid, bool owner)
		{
			return valid && owner;
		}

		internal static bool CanSupply(SupplySnapshot source, float x, float y, float z, float range, float minimum, long now)
		{
			if (!source.Valid || !Fresh(now, source.Updated) || !Finite(range) || range <= 0f || !Finite(minimum) || minimum < 0f || minimum > 1f || !Finite(source.Output) || source.Output <= minimum || source.Output > 1f || !Finite(source.X) || !Finite(source.Y) || !Finite(source.Z) || !Finite(x) || !Finite(y) || !Finite(z))
			{
				return false;
			}
			double num = (double)source.X - (double)x;
			double num2 = (double)source.Y - (double)y;
			double num3 = (double)source.Z - (double)z;
			return num * num + num2 * num2 + num3 * num3 <= (double)range * (double)range;
		}

		internal static bool HasSupply(IEnumerable<SupplySnapshot> sources, float x, float y, float z, float range, float minimum, long now)
		{
			foreach (SupplySnapshot source in sources)
			{
				if (CanSupply(source, x, y, z, range, minimum, now))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool ConsumerOn(bool powered, long now, long updated)
		{
			if (powered)
			{
				return Fresh(now, updated);
			}
			return false;
		}

		internal static float SanitizeOutput(float output)
		{
			if (!Finite(output))
			{
				return 0f;
			}
			return Math.Max(0f, Math.Min(1f, output));
		}
	}
	internal static class Models
	{
		private static Material wood;

		private static Material iron;

		private static Material copper;

		private static Material glow;

		private static Material stone;

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

		private static readonly Dictionary<Surface, Material> artMaterials = new Dictionary<Surface, Material>();

		internal static void Initialize()
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			if (PowerElecPlugin.Headless)
			{
				return;
			}
			Shader val = Shader.Find("Custom/Piece");
			if (!Object.op_Implicit((Object)(object)val))
			{
				MeshRenderer[] componentsInChildren = PowerElecPlugin.Prefab("wood_pole").GetComponentsInChildren<MeshRenderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Material[] sharedMaterials = ((Renderer)componentsInChildren[i]).sharedMaterials;
					foreach (Material val2 in sharedMaterials)
					{
						if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.shader) && ((Object)val2.shader).name == "Custom/Piece")
						{
							val = val2.shader;
						}
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = Shader.Find("Standard");
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Opaque model shader missing.");
			}
			wood = Material(val, "PowerElec_BlackTimber", new Color(0.11f, 0.085f, 0.065f), 0.03f, 0.18f);
			Texture2D val3 = new Texture2D(32, 128, (TextureFormat)4, false);
			((Object)val3).name = "PowerElec_TimberGrain";
			Color[] array = (Color[])(object)new Color[4096];
			for (int k = 0; k < 128; k++)
			{
				for (int l = 0; l < 32; l++)
				{
					float num = 0.65f + 0.25f * Mathf.Sin((float)l * 2.1f + Mathf.Sin((float)k * 0.08f) * 0.6f);
					array[k * 32 + l] = new Color(num, num, num, 1f);
				}
			}
			val3.SetPixels(array);
			((Texture)val3).wrapMode = (TextureWrapMode)0;
			val3.Apply(false, true);
			wood.SetTexture("_MainTex", (Texture)(object)val3);
			iron = Material(val, "PowerElec_BlackIron", new Color(0.07f, 0.075f, 0.08f), 0.7f, 0.3f);
			copper = Material(val, "PowerElec_Copper", new Color(0.57f, 0.26f, 0.095f), 0.72f, 0.4f);
			stone = Material(val, "PowerElec_Stone", new Color(0.2f, 0.2f, 0.19f), 0.05f, 0.1f);
			glow = Material(val, "PowerElec_Amber", new Color(1f, 0.48f, 0.08f), 0.1f, 0.3f);
			if (glow.HasProperty("_EmissionColor"))
			{
				glow.SetColor("_EmissionColor", new Color(1.8f, 0.65f, 0.09f));
			}
			glow.EnableKeyword("_EMISSION");
		}

		private static Material Material(Shader shader, string name, Color color, float metal, float shine)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(shader)
			{
				name = name,
				renderQueue = 2000,
				shaderKeywords = new string[0]
			};
			if (val.HasProperty("_MainTex"))
			{
				val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", color);
			}
			string[] array = new string[9] { "_Cutoff", "_ValueNoise", "_ValueNoiseVertex", "_AddSnow", "_AddRain", "_TriplanarMap", "_MoveableObject", "_Mode", "_BumpScale" };
			foreach (string text in array)
			{
				if (val.HasProperty(text))
				{
					val.SetFloat(text, 0f);
				}
			}
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", metal);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", shine);
			}
			if (val.HasProperty("_EmissionColor"))
			{
				val.SetColor("_EmissionColor", Color.black);
			}
			if (val.HasProperty("_SrcBlend"))
			{
				val.SetFloat("_SrcBlend", 1f);
			}
			if (val.HasProperty("_DstBlend"))
			{
				val.SetFloat("_DstBlend", 0f);
			}
			if (val.HasProperty("_ZWrite"))
			{
				val.SetFloat("_ZWrite", 1f);
			}
			return val;
		}

		internal static Sprite Icon(string key, Sprite fallback)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (icons.TryGetValue(key, out var value))
			{
				return value;
			}
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PowerElec.Icons." + key + ".png");
			if (stream == null)
			{
				return fallback;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num == 0)
				{
					throw new EndOfStreamException("Truncated icon resource: " + key);
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).name = "PowerElec_Icon_" + key;
			MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			});
			if (method == null || !(bool)method.Invoke(null, new object[3] { val, array, true }))
			{
				return fallback;
			}
			value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			icons.Add(key, value);
			return value;
		}

		private static GameObject Child(Transform parent, string name, Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.layer = ((Component)parent).gameObject.layer;
			return val;
		}

		private static GameObject Shape(Transform parent, string name, PrimitiveType type, Vector3 position, Vector3 scale, Material material, bool solid = false)
		{
			//IL_0000: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = position;
			obj.transform.localScale = scale;
			obj.layer = ((Component)parent).gameObject.layer;
			Collider component = obj.GetComponent<Collider>();
			if (!solid && Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			if (PowerElecPlugin.Headless)
			{
				((Renderer)component2).enabled = false;
				return obj;
			}
			((Renderer)component2).sharedMaterial = material;
			return obj;
		}

		private static GameObject Box(Transform parent, string name, Vector3 position, Vector3 scale, Material material, bool solid = false)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return Shape(parent, name, (PrimitiveType)3, position, scale, material, solid);
		}

		private static void Rod(Transform parent, Vector3 start, Vector3 end, float width, Material material)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			Box(parent, "Metal brace", (start + end) * 0.5f, new Vector3(width, Vector3.Distance(start, end), width), material).transform.localRotation = Quaternion.FromToRotation(Vector3.up, end - start);
		}

		internal static void ClearPiece(GameObject go)
		{
			LODGroup[] componentsInChildren = go.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			for (int num = go.transform.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)go.transform.GetChild(num)).gameObject);
			}
			Collider[] components = go.GetComponents<Collider>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			Renderer[] components2 = go.GetComponents<Renderer>();
			for (int i = 0; i < components2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components2[i]);
			}
			MeshFilter[] components3 = go.GetComponents<MeshFilter>();
			for (int i = 0; i < components3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components3[i]);
			}
		}

		internal static void BuildHammer(GameObject item)
		{
			//IL_008a: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: 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_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			Transform val = item.transform.Find("attach");
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Native hammer attach point missing.");
			}
			LODGroup[] componentsInChildren = ((Component)val).GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			MeshFilter[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Transform transform = Child(val, "PowerElecHammerModel", Vector3.zero).transform;
			Box(transform, "Black timber grip", new Vector3(0f, 0.12f, 0f), new Vector3(0.065f, 0.43f, 0.065f), wood);
			Box(transform, "Forged head", new Vector3(0f, 0.39f, 0f), new Vector3(0.3f, 0.15f, 0.13f), iron);
			for (int j = 0; j < 2; j++)
			{
				Box(transform, "Copper head band", new Vector3((j == 0) ? (-0.095f) : 0.095f, 0.39f, 0f), new Vector3(0.025f, 0.16f, 0.14f), copper);
			}
			Box(transform, "Copper pommel", new Vector3(0f, -0.09f, 0f), new Vector3(0.08f, 0.035f, 0.08f), copper);
			for (int k = 0; k < 5; k++)
			{
				Box(transform, "Grip wrap", new Vector3(0f, (float)k * 0.046f, 0f), new Vector3(0.071f, 0.012f, 0.071f), iron);
			}
			Rod(transform, new Vector3(0.025f, 0.445f, -0.069f), new Vector3(-0.02f, 0.39f, -0.069f), 0.012f, glow);
			Rod(transform, new Vector3(-0.02f, 0.39f, -0.069f), new Vector3(0.018f, 0.39f, -0.069f), 0.012f, glow);
			Rod(transform, new Vector3(0.018f, 0.39f, -0.069f), new Vector3(-0.025f, 0.34f, -0.069f), 0.012f, glow);
		}

		private static Vector3 Vec(V v)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(v.X, v.Y, v.Z);
		}

		private static Material ArtMaterial(Surface surface)
		{
			//IL_0040: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00df: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			if (PowerElecPlugin.Headless)
			{
				return null;
			}
			if (artMaterials.TryGetValue(surface, out var value))
			{
				return value;
			}
			value = Material(wood.shader, "PowerElec_" + surface.ToString() + "_011", Color.white, surface switch
			{
				Surface.Iron => 0.5f, 
				Surface.Copper => 0.65f, 
				_ => 0.02f, 
			}, 0.22f);
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = "PowerElec_" + surface.ToString() + "_WornSurface",
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float[] array2 = ArtPalette.Pixel(surface, j, i);
					array[i * 64 + j] = new Color(array2[0], array2[1], array2[2], 1f);
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			value.SetTexture("_MainTex", (Texture)(object)val);
			if (surface == Surface.Glow || surface == Surface.BlueGlow || surface == Surface.GreenGlow)
			{
				if (value.HasProperty("_EmissionColor"))
				{
					value.SetColor("_EmissionColor", (Color)(surface switch
					{
						Surface.GreenGlow => new Color(0.45f, 1.5f, 0.25f), 
						Surface.BlueGlow => new Color(0.28f, 0.75f, 1.5f), 
						_ => new Color(1.25f, 0.46f, 0.06f), 
					}));
				}
				value.EnableKeyword("_EMISSION");
			}
			artMaterials.Add(surface, value);
			return value;
		}

		private static GameObject Apply(GameObject root, Plan plan, int tint = 0)
		{
			LampVariants.Colorize(plan, tint);
			return ApplyPlan(root, plan, tint);
		}

		private static GameObject ApplyPlan(GameObject root, Plan plan, int tint)
		{
			//IL_000b: 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_0077: 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)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Child(root.transform, "PowerElecModel", Vector3.zero);
			GameObject val2 = Child(val.transform, "PoweredGlow", Vector3.zero);
			val2.SetActive(false);
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>
			{
				{ "static", val.transform },
				{ "glow", val2.transform }
			};
			if (plan.IsTurbine)
			{
				GameObject val3 = Child(val.transform, "Yaw", Vec(plan.Yaw));
				dictionary.Add("yaw", val3.transform);
				dictionary.Add("rotor", Child(val3.transform, "Rotor", Vec(plan.Rotor)).transform);
				dictionary.Add("dynamo", Child(val3.transform, "Dynamo", Vec(plan.Dynamo)).transform);
			}
			int num = 0;
			foreach (Batch batch in plan.Batches)
			{
				GameObject val4 = Child(dictionary[batch.Group], batch.Material.ToString() + " mesh", Vector3.zero);
				Vector3[] array = (Vector3[])(object)new Vector3[batch.Mesh.Vertices.Count];
				Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = Vec(batch.Mesh.Vertices[i]);
					V v = batch.Mesh.UV[i];
					array2[i] = new Vector2(v.X, v.Y);
				}
				Mesh val5 = new Mesh();
				((Object)val5).name = "PowerElec_" + ((Object)root).name + "_" + batch.Group + "_" + batch.Material;
				Mesh val6 = val5;
				if (array.Length > 65535)
				{
					val6.indexFormat = (IndexFormat)1;
				}
				val6.vertices = array;
				val6.uv = array2;
				val6.triangles = batch.Mesh.Triangles.ToArray();
				val6.RecalculateNormals();
				val6.RecalculateBounds();
				val4.AddComponent<MeshFilter>().sharedMesh = val6;
				MeshRenderer val7 = val4.AddComponent<MeshRenderer>();
				((Renderer)val7).enabled = !PowerElecPlugin.Headless;
				if (!PowerElecPlugin.Headless)
				{
					((Renderer)val7).sharedMaterial = ArtMaterial(batch.Material);
				}
				num += array.Length;
			}
			int num2 = 0;
			foreach (HitBox collider in plan.Colliders)
			{
				GameObject obj = Child(val.transform, "Solid support " + num2++, Vec(collider.Position));
				obj.transform.localRotation = ((collider.Direction.Length > 0f) ? Quaternion.FromToRotation(Vector3.up, Vec(collider.Direction)) : Quaternion.Euler(0f, collider.YAngle, collider.ZAngle));
				obj.AddComponent<BoxCollider>().size = Vec(collider.Size);
			}
			if (!plan.IsTurbine && !PowerElecPlugin.Headless)
			{
				if (plan.IsHeater)
				{
					Light obj2 = Child(val2.transform, "Warm amber light", Vec(plan.Light)).AddComponent<Light>();
					obj2.type = (LightType)2;
					obj2.color = new Color(1f, 0.66f, 0.32f);
					obj2.range = plan.Radius;
					obj2.intensity = plan.Intensity;
					obj2.shadows = (LightShadows)0;
				}
				else
				{
					int num3 = ((!((Object)root).name.StartsWith("PowerElec_Pendant", StringComparison.Ordinal)) ? (((Object)root).name.StartsWith("PowerElec_GardenLamp", StringComparison.Ordinal) ? 1 : 3) : 0);
					GameObject obj3 = Child(val.transform, "PoweredRoomLight", Vec(plan.Light) + new Vector3(0f, -0.1f, (num3 == 3) ? (-0.12f) : 0f));
					obj3.layer = 0;
					((Behaviour)obj3.AddComponent<Light>()).enabled = false;
					obj3.AddComponent<RoomLighting>().Configure(num3, tint);
				}
			}
			if (plan.IsHeater)
			{
				GameObject obj4 = Child(val.transform, "PoweredHeat", new Vector3(0f, 0.6f, 0f));
				obj4.SetActive(false);
				int num4 = LayerMask.NameToLayer("character_trigger");
				if (num4 < 0)
				{
					throw new InvalidOperationException("Native character_trigger layer missing.");
				}
				obj4.layer = num4;
				SphereCollider obj5 = obj4.AddComponent<SphereCollider>();
				((Collider)obj5).isTrigger = true;
				obj5.radius = PowerElecPlugin.Instance.HeatRadius.Value;
				EffectArea obj6 = obj4.AddComponent<EffectArea>();
				obj6.m_type = (Type)1;
				obj6.m_playerOnly = true;
				obj6.m_statusEffect = "";
			}
			PowerElecPlugin.LogModelInfo(((Object)root).name + ": " + plan.Batches.Count + " material batches, " + num + " mesh vertices.");
			return val;
		}

		internal static GameObject BuildTurbine(GameObject root, Windmill native)
		{
			//IL_0062: 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_019e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Apply(root, Designs.Turbine());
			Windmill val2 = root.AddComponent<Windmill>();
			val2.m_bom = val.transform.Find("Yaw");
			val2.m_propeller = val.transform.Find("Yaw/Rotor");
			val2.m_grindstone = val.transform.Find("Yaw/Dynamo");
			val2.m_propellerAOE = Child(val.transform, "Unused native rotor trigger", Vector3.zero);
			val2.m_propellerAOE.SetActive(false);
			val2.m_minAOEPropellerSpeed = float.MaxValue;
			val2.m_minWindSpeed = native.m_minWindSpeed;
			val2.m_bomRotationSpeed = native.m_bomRotationSpeed;
			val2.m_propellerRotationSpeed = native.m_propellerRotationSpeed;
			val2.m_grindstoneRotationSpeed = native.m_grindstoneRotationSpeed;
			val2.m_minPitch = native.m_minPitch;
			val2.m_maxPitch = native.m_maxPitch;
			val2.m_maxPitchVel = native.m_maxPitchVel;
			val2.m_maxVol = native.m_maxVol;
			val2.m_maxVolVel = native.m_maxVolVel;
			val2.m_audioChangeSpeed = native.m_audioChangeSpeed;
			List<AudioSource> list = new List<AudioSource>();
			AudioSource[] sfxLoops = native.m_sfxLoops;
			foreach (AudioSource val3 in sfxLoops)
			{
				if (Object.op_Implicit((Object)(object)val3))
				{
					AudioSource val4 = Child(val.transform, "Wind ambience", new Vector3(0f, 3.5f, 0f)).AddComponent<AudioSource>();
					val4.clip = val3.clip;
					val4.loop = true;
					val4.playOnAwake = true;
					val4.spatialBlend = val3.spatialBlend;
					val4.minDistance = val3.minDistance;
					val4.maxDistance = val3.maxDistance;
					val4.rolloffMode = val3.rolloffMode;
					val4.volume = val3.volume;
					val4.pitch = val3.pitch;
					val4.outputAudioMixerGroup = val3.outputAudioMixerGroup;
					list.Add(val4);
				}
			}
			val2.m_sfxLoops = list.ToArray();
			return val;
		}

		internal static GameObject BuildPendant(GameObject root)
		{
			return Apply(root, Designs.Pendant());
		}

		internal static GameObject BuildWall(GameObject root)
		{
			return Apply(root, Designs.Wall());
		}

		internal static GameObject BuildHeater(GameObject root)
		{
			return Apply(root, Designs.Heater());
		}

		internal static GameObject BuildColored(GameObject root, int kind, int tint)
		{
			if (kind != 1)
			{
				return Apply(root, (kind == 0) ? Designs.Pendant() : Designs.Wall(), tint);
			}
			return BuildGarden(root, tint);
		}

		internal static GameObject BuildGarden(GameObject root)
		{
			return BuildGarden(root, 0);
		}

		private static GameObject BuildGarden(GameObject root, int tint)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PowerElecPlugin.Prefab("piece_dvergr_lantern_pole");
			float num = float.MaxValue;
			float num2 = float.MinValue;
			MeshFilter[] componentsInChildren = val.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val2 in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val2.sharedMesh) && Object.op_Implicit((Object)(object)((Component)val2).GetComponent<MeshRenderer>()))
				{
					Bounds bounds = val2.sharedMesh.bounds;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
						float y = val.transform.InverseTransformPoint(((Component)val2).transform.TransformPoint(val3)).y;
						num = Mathf.Min(num, y);
						num2 = Mathf.Max(num2, y);
					}
				}
			}
			float nativeHeight = num2 - num;
			Plan plan = Designs.Garden(nativeHeight);
			PowerElecPlugin.LogModelInfo("Garden lamp height matched to native piece_dvergr_lantern_pole: " + nativeHeight.ToString("0.000") + "m.");
			return Apply(root, plan, tint);
		}

		internal static void SetRenderedIcon(GameObject prefab)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (PowerElecPlugin.Headless)
			{
				return;
			}
			try
			{
				Transform val = prefab.transform.Find("PowerElecModel");
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new InvalidOperationException("Piece visual root missing.");
				}
				Transform val2 = val.Find("PoweredGlow");
				bool active = Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeSelf;
				try
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						((Component)val2).gameObject.SetActive(true);
					}
					Sprite val3 = RenderManager.Instance.Render(((Component)val).gameObject, RenderManager.IsometricRotation);
					if (Object.op_Implicit((Object)(object)val3))
					{
						prefab.GetComponent<Piece>().m_icon = val3;
					}
				}
				finally
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						((Component)val2).gameObject.SetActive(active);
					}
				}
			}
			catch (Exception e)
			{
				PowerElecPlugin.LogError("Using embedded icon because native model render failed", e);
			}
		}
	}
	internal struct LampPreset
	{
		internal float Intensity;

		internal float Range;

		internal LampPreset(float intensity, float range)
		{
			Intensity = intensity;
			Range = range;
		}
	}
	internal struct LampColor
	{
		internal float R;

		internal float G;

		internal float B;

		internal LampColor(float r, float g, float b)
		{
			R = r;
			G = g;
			B = b;
		}
	}
	internal static class LampPolicy
	{
		internal static int Percent(int value)
		{
			return Math.Max(20, Math.Min(100, value));
		}

		internal static int FromLegacy(float multiplier)
		{
			if (!float.IsNaN(multiplier) && !float.IsInfinity(multiplier) && !(multiplier <= 0f))
			{
				return Percent((int)Math.Round(Math.Min(4f, multiplier) * 60f));
			}
			return 60;
		}

		internal static bool CanAdjust(long actor, long actorOwner, long sender, float distance, bool alive, int percent)
		{
			if (actor != 0L && actorOwner == sender && alive && !float.IsNaN(distance) && !float.IsInfinity(distance) && distance >= 0f && distance <= 4.5f && percent >= 20)
			{
				return percent <= 100;
			}
			return false;
		}

		internal static LampColor Color(int tint)
		{
			return tint switch
			{
				2 => new LampColor(0.35f, 1f, 0.3f), 
				1 => new LampColor(0.28f, 0.65f, 1f), 
				_ => new LampColor(1f, 0.78f, 0.48f), 
			};
		}

		internal static LampPreset AtPercent(int kind, int percent, float reach)
		{
			return Resolve(kind, (float)Percent(percent) / 60f, reach);
		}

		internal static LampPreset Resolve(int kind, float brightness, float reach)
		{
			if (float.IsNaN(brightness) || float.IsInfinity(brightness) || brightness <= 0f)
			{
				brightness = 1f;
			}
			if (float.IsNaN(reach) || float.IsInfinity(reach) || reach <= 0f)
			{
				reach = 1f;
			}
			brightness = Math.Max(0.25f, Math.Min(4f, brightness));
			reach = Math.Max(0.5f, Math.Min(2f, reach));
			LampPreset lampPreset = kind switch
			{
				0 => new LampPreset(3.6f, 16f), 
				1 => new LampPreset(3f, 18f), 
				3 => new LampPreset(2.4f, 14f), 
				_ => throw new ArgumentOutOfRangeException("kind", "Room lighting presets do not apply to the heater."), 
			};
			return new LampPreset(lampPreset.Intensity * brightness, lampPreset.Range * reach);
		}
	}
	public sealed class RoomLighting : MonoBehaviour
	{
		[SerializeField]
		private int kind;

		[SerializeField]
		private int tint;

		private Light lamp;

		private bool configured;

		private bool loggedOn;

		private float lastBrightness;

		private float lastReach;

		internal void Configure(int value, int color = 0)
		{
			kind = value;
			tint = color;
			SetPowered(powered: false);
		}

		private void Awake()
		{
			lamp = ((Component)this).GetComponent<Light>();
			SetPowered(powered: false);
		}

		public void SetPowered(bool powered, int percent = 60)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)lamp))
			{
				lamp = ((Component)this).GetComponent<Light>();
			}
			if (Object.op_Implicit((Object)(object)lamp))
			{
				float num = LampPolicy.Percent(percent);
				float num2 = (Object.op_Implicit((Object)(object)PowerElecPlugin.Instance) ? PowerElecPlugin.Instance.LampReach.Value : 1f);
				if (!configured || num != lastBrightness || num2 != lastReach)
				{
					LampPreset lampPreset = LampPolicy.AtPercent(kind, (int)num, num2);
					lamp.type = (LightType)2;
					LampColor lampColor = LampPolicy.Color(tint);
					lamp.color = new Color(lampColor.R, lampColor.G, lampColor.B);
					lamp.useColorTemperature = false;
					lamp.range = lampPreset.Range;
					lamp.intensity = lampPreset.Intensity;
					lamp.renderMode = (LightRenderMode)1;
					lamp.cullingMask = -1;
					lamp.renderingLayerMask = -1;
					lamp.bakingOutput = new LightBakingOutput
					{
						isBaked = false,
						lightmapBakeType = (LightmapBakeType)4
					};
					lamp.shadows = (LightShadows)0;
					lamp.bounceIntensity = 1f;
					configured = true;
					lastBrightness = num;
					lastReach = num2;
				}
				((Behaviour)lamp).enabled = powered;
				if (powered && !loggedOn)
				{
					loggedOn = true;
					PowerElecPlugin.LogModelInfo("Room lamp kind " + kind + " enabled: intensity=" + lamp.intensity + ", reach=" + lamp.range + "m, mode=" + ((object)lamp.renderMode/*cast due to .constrained prefix*/).ToString() + ", receiverMask=" + lamp.cullingMask + ", renderingLayers=" + lamp.renderingLayerMask);
				}
			}
		}

		private void OnDisable()
		{
			if (Object.op_Implicit((Object)(object)lamp))
			{
				((Behaviour)lamp).enabled = false;
			}
		}
	}
	internal sealed class LampVariant
	{
		internal int Kind;

		internal int Tint;

		internal string Name;

		internal string Token;

		internal string BaseItem;

		internal string ColorItem;

		internal LampVariant(int kind, int tint)
		{
			Kind = kind;
			Tint = tint;
			Name = LampVariants.Name(kind, tint);
			Token = LampVariants.Token(kind, tint);
			BaseItem = ((kind == 1) ? "RoundLog" : "Wood");
			ColorItem = ((tint == 1) ? "GreydwarfEye" : "Guck");
		}
	}
	internal static class LampVariants
	{
		internal static LampVariant[] Added()
		{
			return new LampVariant[6]
			{
				new LampVariant(0, 1),
				new LampVariant(1, 1),
				new LampVariant(3, 1),
				new LampVariant(0, 2),
				new LampVariant(1, 2),
				new LampVariant(3, 2)
			};
		}

		internal static string Name(int kind, int tint)
		{
			return kind switch
			{
				1 => "PowerElec_GardenLamp", 
				0 => "PowerElec_Pendant", 
				_ => "PowerElec_WallLamp", 
			} + tint switch
			{
				2 => "_Green", 
				1 => "_Blue", 
				_ => "", 
			};
		}

		internal static string Token(int kind, int tint)
		{
			return kind switch
			{
				3 => "pe_wall", 
				1 => "pe_garden", 
				0 => "pe_pendant", 
				_ => "pe_heater", 
			} + tint switch
			{
				2 => "_green", 
				1 => "_blue", 
				_ => "", 
			};
		}

		internal static Plan Colorize(Plan plan, int tint)
		{
			if (!plan.IsHeater && !plan.IsTurbine)
			{
				switch (tint)
				{
				case 0:
					break;
				default:
					throw new ArgumentOutOfRangeException("tint");
				case 1:
				case 2:
				{
					foreach (Batch batch in plan.Batches)
					{
						if (batch.Material == Surface.Amber)
						{
							batch.Material = ((tint == 1) ? Surface.BlueCore : Surface.GreenCore);
						}
						else if (batch.Material == Surface.Glow)
						{
							batch.Material = ((tint == 1) ? Surface.BlueGlow : Surface.GreenGlow);
						}
					}
					return plan;
				}
				}
			}
			return plan;
		}
	}
	public sealed class LampSettings : MonoBehaviour
	{
		private const string Key = "pe_lamp_percent_v1";

		private ZNetView view;

		private float nextDefault;

		internal bool Valid
		{
			get
			{
				if (Object.op_Implicit((Object)(object)view))
				{
					return view.IsValid();
				}
				return false;
			}
		}

		internal int Percent
		{
			get
			{
				int num = (Object.op_Implicit((Object)(object)PowerElecPlugin.Instance) ? PowerElecPlugin.Instance.DefaultLampBrightness.Value : 60);
				int num2 = (Valid ? view.GetZDO().GetInt("pe_lamp_percent_v1", 0) : 0);
				return LampPolicy.Percent((num2 == 0) ? num : num2);
			}
		}

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			if (Valid)
			{
				view.Register<long, int>("pe_lamp_set", (Action<long, long, int>)RPC_Set);
				view.Register<long, int, bool>("pe_lamp_reply", (Action<long, long, int, bool>)RPC_Reply);
			}
		}

		private void Update()
		{
			if (!(Time.time < nextDefault))
			{
				nextDefault = Time.time + 1f;
				if (Valid && view.IsOwner() && view.GetZDO().GetInt("pe_lamp_percent_v1", 0) == 0)
				{
					view.GetZDO().Set("pe_lamp_percent_v1", Percent);
				}
			}
		}

		internal bool Open(Player player)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid || !Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || ((Character)player).IsDead() || ((Character)player).IsTeleporting() || ((Character)player).IsAttached() || Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position) > 4.5f)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			LampSettingsUI.Open(this);
			return true;
		}

		internal void Request(int percent)
		{
			Player localPlayer = Player.m_localPlayer;
			if (Valid && Object.op_Implicit((Object)(object)localPlayer))
			{
				view.InvokeRPC("pe_lamp_set", new object[2]
				{
					localPlayer.GetPlayerID(),
					percent
				});
			}
		}

		private void RPC_Set(long sender, long actor, int percent)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (Valid && view.IsOwner())
			{
				Player player = Player.GetPlayer(actor);
				bool flag = Object.op_Implicit((Object)(object)player) && LampPolicy.CanAdjust(actor, ((Character)player).GetOwner(), sender, Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position), !((Character)player).IsDead() && !((Character)player).IsTeleporting(), percent) && WardAccess.Allowed(((Component)this).transform.position, actor);
				if (flag)
				{
					view.GetZDO().Set("pe_lamp_percent_v1", percent);
				}
				view.InvokeRPC(sender, "pe_lamp_reply", new object[3]
				{
					actor,
					flag ? percent : Percent,
					flag
				});
			}
		}

		private void RPC_Reply(long sender, long actor, int percent, bool allowed)
		{
			Player localPlayer = Player.m_localPlayer;
			if (Valid && sender == view.GetZDO().GetOwner() && Object.op_Implicit((Object)(object)localPlayer) && localPlayer.GetPlayerID() == actor)
			{
				LampSettingsUI.Reply(this, percent, allowed);
			}
		}

		private void OnDestroy()
		{
			LampSettingsUI.CloseFor(this);
		}
	}
	public sealed class LampSettingsUI : MonoBehaviour
	{
		private static LampSettingsUI instance;

		private LampSettings target;

		private int percent;

		private bool inputHeld;

		private bool waiting;

		private float deadline;

		private string status = "";

		private void Awake()
		{
			instance = this;
		}

		internal static void Open(LampSettings lamp)
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.Close();
				instance.target = lamp;
				instance.percent = lamp.Percent;
				instance.status = "";
				GUIManager.BlockInput(true);
				instance.inputHeld = true;
			}
		}

		private void Close()
		{
			target = null;
			waiting = false;
			if (inputHeld)
			{
				inputHeld = false;
				GUIManager.BlockInput(false);
			}
		}

		internal static void CloseFor(LampSettings lamp)
		{
			if (Object.op_Implicit((Object)(object)instance) && (Object)(object)instance.target == (Object)(object)lamp)
			{
				instance.Close();
			}
		}

		internal static void Reply(LampSettings lamp, int value, bool allowed)
		{
			if (Object.op_Implicit((Object)(object)instance) && !((Object)(object)instance.target != (Object)(object)lamp) && instance.waiting)
			{
				instance.waiting = false;
				if (allowed)
				{
					instance.percent = LampPolicy.Percent(value);
					instance.Close();
				}
				else
				{
					instance.status = "Cannot adjust this lamp. Check distance and ward access.";
				}
			}
		}

		private void Update()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!target.Valid || !Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)target).transform.position) > 5f || Input.GetKeyDown((KeyCode)27))
				{
					Close();
				}
				else if (waiting && Time.unscaledTime > deadline)
				{
					waiting = false;
					status = "No reply from the lamp owner. Please try again.";
				}
			}
		}

		private void OnGUI()
		{
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00c2: 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)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			Matrix4x4 matrix = GUI.matrix;
			Color color = GUI.color;
			bool enabled = GUI.enabled;
			try
			{
				float num = Mathf.Clamp((float)Screen.height / 1080f, 0.7f, 1.6f);
				GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * num);
				float num2 = ((float)Screen.width / num - 460f) / 2f;
				float num3 = ((float)Screen.height / num - 290f) / 2f;
				GUI.color = new Color(0.035f, 0.045f, 0.05f, 0.98f);
				GUI.DrawTexture(new Rect(num2, num3, 460f, 290f), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Color.white;
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1
				};
				val.normal.textColor = new Color(0.95f, 0.76f, 0.42f);
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 17,
					wordWrap = true
				};
				GUI.Label(new Rect(num2 + 24f, num3 + 17f, 420f, 32f), "LAMP BRIGHTNESS", val);
				ElectricAppliance component = ((Component)target).GetComponent<ElectricAppliance>();
				GUI.Label(new Rect(num2 + 24f, num3 + 55f, 420f, 28f), Object.op_Implicit((Object)(object)component) ? component.GetHoverName() : "Power Elec Lamp", val2);
				GUI.Label(new Rect(num2 + 24f, num3 + 90f, 420f, 28f), "Brightness: " + percent + "%", val2);
				GUI.enabled = !waiting;
				percent = LampPolicy.Percent(Mathf.RoundToInt(GUI.HorizontalSlider(new Rect(num2 + 30f, num3 + 131f, 400f, 24f), (float)percent, 20f, 100f)));
				GUI.Label(new Rect(num2 + 24f, num3 + 157f, 120f, 25f), "20%", val2);
				GUI.Label(new Rect(num2 + 376f, num3 + 157f, 70f, 25f), "100%", val2);
				GUI.Label(new Rect(num2 + 24f, num3 + 188f, 416f, 40f), (status.Length > 0) ? status : "Apply saves this lamp for everyone.", val2);
				if (GUI.Button(new Rect(num2 + 24f, num3 + 241f, 196f, 30f), "Cancel"))
				{
					Close();
				}
				if (GUI.Button(new Rect(num2 + 240f, num3 + 241f, 196f, 30f), waiting ? "Saving..." : "Apply"))
				{
					waiting = true;
					deadline = Time.unscaledTime + 6f;
					status = "Saving...";
					target.Request(percent);
				}
			}
			finally
			{
				GUI.matrix = matrix;
				GUI.color = color;
				GUI.enabled = enabled;
			}
		}

		private void OnDisable()
		{
			Close();
		}

		private void OnDestroy()
		{
			Close();
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
	internal static class WardAccess
	{
		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly FieldInfo Areas = typeof(PrivateArea).GetField("m_allAreas", BindingFlags.Static | BindingFlags.NonPublic);

		private static readonly MethodInfo Enabled = typeof(PrivateArea).GetMethod("IsEnabled", Flags);

		private static readonly MethodInfo Inside = typeof(PrivateArea).GetMethod("IsInside", Flags);

		private static readonly MethodInfo Permitted = typeof(PrivateArea).GetMethod("IsPermitted", Flags);

		internal static bool Allowed(Vector3 position, long actor)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (Areas == null || Enabled == null || Inside == null || Permitted == null)
			{
				return false;
			}
			bool flag = false;
			try
			{
				foreach (PrivateArea item in (IEnumerable<PrivateArea>)Areas.GetValue(null))
				{
					if (Object.op_Implicit((Object)(object)item) && (bool)Enabled.Invoke(item, null) && (bool)Inside.Invoke(item, new object[2] { position, 0f }))
					{
						flag = true;
						Piece component = ((Component)item).GetComponent<Piece>();
						if ((Object.op_Implicit((Object)(object)component) && component.GetCreator() == actor) || (bool)Permitted.Invoke(item, new object[1] { actor }))
						{
							return true;
						}
					}
				}
				return !flag;
			}
			catch (Exception e)
			{
				PowerElecPlugin.LogError("Ward access validation failed", e);
				return false;
			}
		}
	}
}
namespace PowerElec.Art
{
	internal struct V
	{
		public float X;

		public float Y;

		public float Z;

		public float Length => (float)Math.Sqrt(X * X + Y * Y + Z * Z);

		public V Unit
		{
			get
			{
				float length = Length;
				if (!(length > 0f))
				{
					return default(V);
				}
				return this * (1f / length);
			}
		}

		public V(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public static V operator +(V a, V b)
		{
			return new V(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
		}

		public static V operator -(V a, V b)
		{
			return new V(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
		}

		public static V operator *(V a, float s)
		{
			return new V(a.X * s, a.Y * s, a.Z * s);
		}

		public static V Cross(V a, V b)
		{
			return new V(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
		}
	}
	internal enum Surface
	{
		Wood,
		Iron,
		Copper,
		Stone,
		Linen,
		Amber,
		Glow,
		BlueCore,
		BlueGlow,
		GreenCore,
		GreenGlow
	}
	internal sealed class Draft
	{
		public readonly List<V> Vertices = new List<V>();

		public readonly List<int> Triangles = new List<int>();

		public readonly List<V> UV = new List<V>();

		public void Face(params V[] points)
		{
			int count = Vertices.Count;
			V v = V.Cross(points[1] - points[0], points[2] - points[0]);
			for (int i = 0; i < points.Length; i++)
			{
				V item = points[i];
				Vertices.Add(item);
				UV.Add((Math.Abs(v.Y) > Math.Abs(v.X) && Math.Abs(v.Y) > Math.Abs(v.Z)) ? new V(item.X * 2f, item.Z * 2f, 0f) : ((Math.Abs(v.X) > Math.Abs(v.Z)) ? new V(item.Z * 2f, item.Y * 2f, 0f) : new V(item.X * 2f, item.Y * 2f, 0f)));
			}
			for (int j = 1; j < points.Length - 1; j++)
			{
				Triangles.Add(count);
				Triangles.Add(count + j);
				Triangles.Add(count + j + 1);
			}
		}

		public void Append(Draft mesh, V pos, V right, V up, V forward)
		{
			int count = Vertices.Count;
			foreach (V vertex in mesh.Vertices)
			{
				Vertices.Add(pos + right * vertex.X + up * vertex.Y + forward * vertex.Z);
			}
			UV.AddRange(mesh.UV);
			foreach (int triangle in mesh.Triangles)
			{
				Triangles.Add(count + triangle);
			}
		}
	}
	internal sealed class Batch
	{
		public string Group;

		public Surface Material;

		public Draft Mesh = new Draft();
	}
	internal sealed class HitBox
	{
		public V Position;

		public V Size;

		public float ZAngle;

		public float YAngle;

		public V Direction;
	}
	internal sealed class Plan
	{
		public readonly List<Batch> Batches = new List<Batch>();

		public readonly List<HitBox> Colliders = new List<HitBox>();

		public V Yaw = new V(0f, 4.6f, 0f);

		public V Rotor = new V(0f, 0f, -0.78f);

		public V Dynamo = new V(0f, 0f, 0.36f);

		public V Light;

		public bool IsTurbine;

		public bool IsHeater;

		public float Radius = 9f;

		public float Intensity = 1.4f;

		public float StaticHeight
		{
			get
			{
				float num = float.MaxValue;
				float num2 = float.MinValue;
				foreach (Batch batch in Batches)
				{
					if (!(batch.Group == "static"))
					{
						continue;
					}
					foreach (V vertex in batch.Mesh.Vertices)
					{
						num = Math.Min(num, vertex.Y);
						num2 = Math.Max(num2, vertex.Y);
					}
				}
				return num2 - num;
			}
		}

		private Batch Get(string group, Surface material)
		{
			foreach (Batch batch2 in Batches)
			{
				if (batch2.Group == group && batch2.Material == material)
				{
					return batch2;
				}
			}
			Batch batch = new Batch
			{
				Group = group,
				Material = material
			};
			Batches.Add(batch);
			return batch;
		}

		public void Add(Draft mesh, Surface material, V position, string group = "static", float zAngle = 0f, float yAngle = 0f)
		{
			double num = (double)zAngle * Math.PI / 180.0;
			double num2 = (double)yAngle * Math.PI / 180.0;
			float num3 = (float)Math.Cos(num);
			float num4 = (float)Math.Sin(num);
			float num5 = (float)Math.Cos(num2);
			float num6 = (float)Math.Sin(num2);
			Get(group, material).Mesh.Append(mesh, position, new V(num3 * num5, num4, (0f - num3) * num6), new V((0f - num4) * num5, num3, num4 * num6), new V(num6, 0f, num5));
		}

		public void Box(Surface material, V p, V size, string group = "static", float angle = 0f, bool solid = false, float yaw = 0f)
		{
			Add(Shapes.Box(size), material, p, group, angle, yaw);
			if (solid)
			{
				Colliders.Add(new HitBox
				{
					Position = p,
					Size = size,
					ZAngle = angle,
					YAngle = yaw
				});
			}
		}

		public void Beam(Surface material, V start, V end, float width, string group = "static", bool solid = false)
		{
			V unit = (end - start).Unit;
			V b = ((Math.Abs(unit.Z) < 0.9f) ? new V(0f, 0f, 1f) : new V(1f, 0f, 0f));
			V unit2 = V.Cross(unit, b).Unit;
			V unit3 = V.Cross(unit2, unit).Unit;
			Get(group, material).Mesh.Append(Shapes.Box(new V(width, (end - start).Length, width)), (start + end) * 0.5f, unit2, unit, unit3);
			if (solid)
			{
				Colliders.Add(new HitBox
				{
					Position = (start + end) * 0.5f,
					Size = new V(width, (end - start).Length, width),
					Direction = unit
				});
			}
		}

		public void Profile(Surface material, V p, int sides, float[] heights, float[] radii, string group = "static", float phase = 0f)
		{
			Add(Shapes.Profile(sides, heights, radii, phase), material, p, group);
		}

		public void Disc(Surface material, V p, int sides, float[] depths, float[] radii, string group)
		{
			Get(group, material).Mesh.Append(Shapes.Profile(sides, depths, radii, 0f), p, new V(1f, 0f, 0f), new V(0f, 0f, 1f), new V(0f, -1f, 0f));
		}

		public void Bolt(V p, float radius = 0.025f, string group = "static")
		{
			Draft mesh = Shapes.Profile(6, new float[2] { -0.008f, 0.008f }, new float[2] { radius, radius }, 0f);
			Get(group, Surface.Copper).Mesh.Append(mesh, p, new V(1f, 0f, 0f), new V(0f, 0f, -1f), new V(0f, 1f, 0f));
		}

		public void Hoop(V center, float radius, float thickness, bool turn, string group = "static")
		{
			Draft mesh = Shapes.Torus(radius, thickness, 10, 5);
			Get(group, Surface.Iron).Mesh.Append(mesh, center, turn ? new V(0f, 0f, 1f) : new V(1f, 0f, 0f), new V(0f, 1f, 0f), turn ? new V(-1f, 0f, 0f) : new V(0f, 0f, 1f));
		}

		public void Scale(float s)
		{
			foreach (Batch batch in Batches)
			{
				for (int i = 0; i < batch.Mesh.Vertices.Count; i++)
				{
					batch.Mesh.Vertices[i] = batch.Mesh.Vertices[i] * s;
				}
			}
			foreach (HitBox collider in Colliders)
			{
				collider.Position *= s;
				collider.Size *= s;
			}
			Light *= s;
		}
	}
	internal static class Shapes
	{
		internal static Draft Box(V size)
		{
			float num = size.X * 0.5f;
			float num2 = size.Y * 0.5f;
			float num3 = size.Z * 0.5f;
			float num4 = Math.Min(num, Math.Min(num2, num3)) * 0.18f;
			Draft draft = new Draft();
			V[][] array = new V[4][];
			for (int i = 0; i < 4; i++)
			{
				float y = i switch
				{
					2 => num2 - num4, 
					1 => 0f - num2 + num4, 
					0 => 0f - num2, 
					_ => num2, 
				};
				float num5 = ((i == 0 || i == 3) ? (num - num4) : num);
				float num6 = ((i == 0 || i == 3) ? (num3 - num4) : num3);
				float num7 = Math.Min(num4, Math.Min(num5, num6) * 0.35f);
				array[i] = new V[8]
				{
					new V(0f - num5 + num7, y, 0f - num6),
					new V(num5 - num7, y, 0f - num6),
					new V(num5, y, 0f - num6 + num7),
					new V(num5, y, num6 - num7),
					new V(num5 - num7, y, num6),
					new V(0f - num5 + num7, y, num6),
					new V(0f - num5, y, num6 - num7),
					new V(0f - num5, y, 0f - num6 + num7)
				};
			}
			for (int j = 0; j < 3; j++)
			{
				for (int k = 0; k < 8; k++)
				{
					int num8 = (k + 1) % 8;
					draft.Face(array[j][k], array[j + 1][k], array[j + 1][num8], array[j][num8]);
				}
			}
			V[] array2 = (V[])array[3].Clone();
			Array.Reverse((Array)array2);
			draft.Face(array2);
			draft.Face(array[0]);
			return draft;
		}

		internal static Draft Profile(int sides, float[] heights, float[] radii, float phase)
		{
			Draft draft = new Draft();
			V[][] array = new V[heights.Length][];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new V[sides];
				for (int j = 0; j < sides; j++)
				{
					double num = Math.PI * 2.0 * (double)j / (double)sides + (double)phase;
					array[i][j] = new V((float)Math.Cos(num) * radii[i], heights[i], (float)Math.Sin(num) * radii[i]);
				}
			}
			for (int k = 0; k < array.Length - 1; k++)
			{
				for (int l = 0; l < sides; l++)
				{
					int num2 = (l + 1) % sides;
					draft.Face(array[k][l], array[k + 1][l], array[k + 1][num2], array[k][num2]);
				}
			}
			draft.Face(array[0]);
			V[] array2 = (V[])array[^1].Clone();
			Array.Reverse((Array)array2);
			draft.Face(array2);
			return draft;
		}

		internal static Draft Torus(float radius, float tube, int major, int minor)
		{
			Draft draft = new Draft();
			Func<int, int, V> func = delegate(int i, int j)
			{
				double num3 = (double)(i * 2) * Math.PI / (double)major;
				double num4 = (double)(j * 2) * Math.PI / (double)minor;
				float num5 = radius + tube * (float)Math.Cos(num4);
				return new V(num5 * (float)Math.Cos(num3), num5 * (float)Math.Sin(num3), tube * (float)Math.Sin(num4));
			};
			for (int num = 0; num < major; num++)
			{
				for (int num2 = 0; num2 < minor; num2++)
				{
					draft.Face(func(num, num2), func(num + 1, num2), func(num + 1, num2 + 1), func(num, num2 + 1));
				}
			}
			return draft;
		}
	}
	internal static class Designs
	{
		internal static Plan Turbine()
		{
			Plan plan = new Plan
			{
				IsTurbine = true
			};
			for (int i = 0; i < 8; i++)
			{
				double num = (double)i * Math.PI / 4.0;
				plan.Box(Surface.Stone, new V((float)Math.Cos(num) * 0.93f, 0.15f, (float)Math.Sin(num) * 0.93f), new V(0.63f, 0.3f + (float)(i % 3) * 0.025f, 0.44f), "static", 0f, solid: true, (float)((0.0 - num) * 180.0 / Math.PI));
			}
			int[] array = new int[2] { -1, 1 };
			float[] array3;
			foreach (int num2 in array)
			{
				int[] array2 = new int[2] { -1, 1 };
				foreach (int num3 in array2)
				{
					V v = new V((float)num2 * 0.8f, 0.22f, (float)num3 * 0.7f);
					V v2 = new V((float)num2 * 0.27f, 4.55f, (float)num3 * 0.27f);
					plan.Beam(Surface.Wood, v, v2, 0.25f, "static", solid: true);
					array3 = new float[3] { 0.52f, 1.9f, 3.65f };
					for (int l = 0; l < array3.Length; l++)
					{
						float num4 = (array3[l] - 0.22f) / 4.33f;
						V v3 = v + (v2 - v) * num4;
						plan.Box(Surface.Copper, v3, new V(0.29f, 0.105f, 0.29f));
						plan.Bolt(v3 + new V(0f, 0f, -0.155f), 0.035f);
					}
				}
			}
			array3 = new float[3] { 0.55f, 2.05f, 3.6f };
			foreach (float num5 in array3)
			{
				float num6 = 0.8f - (num5 - 0.22f) / 4.33f * 0.53f;
				array = new int[2] { -1, 1 };
				foreach (int num7 in array)
				{
					plan.Box(Surface.Wood, new V(0f, num5, (float)num7 * num6), new V(num6 * 2f + 0.18f, 0.16f, 0.19f), "static", 0f, solid: true);
				}
				array = new int[2] { -1, 1 };
				foreach (int num8 in array)
				{
					plan.Box(Surface.Wood, new V((float)num8 * num6, num5, 0f), new V(0.19f, 0.16f, num6 * 2f + 0.18f), "static", 0f, solid: true);
				}
			}
			array = new int[2] { -1, 1 };
			foreach (int num9 in array)
			{
				plan.Beam(Surface.Wood, new V(-0.75f, 0.6f, (float)num9 * 0.7f), new V(0.51f, 2.05f, (float)num9 * 0.51f), 0.11f);
				plan.Beam(Surface.Wood, new V(0.75f, 0.6f, (float)num9 * 0.7f), new V(-0.51f, 2.05f, (float)num9 * 0.51f), 0.11f);
				plan.Beam(Surface.Wood, new V(-0.5f, 2.1f, (float)num9 * 0.5f), new V(0.29f, 3.7f, (float)num9 * 0.29f), 0.1f);
			}
			plan.Box(Surface.Iron, new V(0f, 4.48f, 0f), new V(0.72f, 0.28f, 0.72f));
			plan.Disc(Surface.Copper, new V(0f, 0f, 0.1f), 12, new float[4] { -0.25f, -0.19f, 0.19f, 0.25f }, new float[4] { 0.39f, 0.43f, 0.43f, 0.39f }, "yaw");
			for (int m = 0; m < 7; m++)
			{
				plan.Disc(Surface.Copper, new V(0f, 0f, -0.05f + (float)m * 0.09f), 12, new float[2] { -0.018f, 0.018f }, new float[2] { 0.36f, 0.36f }, "yaw");
			}
			plan.Disc(Surface.Iron, new V(0f, 0f, 0.2f), 12, new float[2] { -0.375f, 0.375f }, new float[2] { 0.33f, 0.33f }, "yaw");
			plan.Box(Surface.Amber, new V(0f, 0f, -0.195f), new V(0.2f, 0.2f, 0.04f), "yaw");
			plan.Disc(Surface.Copper, default(V), 12, new float[4] { -0.14f, -0.1f, 0.1f, 0.14f }, new float[4] { 0.27f, 0.33f, 0.33f, 0.27f }, "rotor");
			for (int n = 0; n < 4; n++)
			{
				float num10 = n * 90 + 25;
				double rad = (double)num10 * Math.PI / 180.0;
				Func<V, V> func = (V v8) => new V(v8.X * (float)Math.Cos(rad) - v8.Y * (float)Math.Sin(rad), v8.X * (float)Math.Sin(rad) + v8.Y * (float)Math.Cos(rad), v8.Z);
				plan.Box(Surface.Wood, func(new V(0f, 1.34f, 0f)), new V(0.1f, 2.68f, 0.1f), "rotor", num10);
				Draft draft = new Draft();
				V v4 = new V(0.1f, 0.76f, -0.015f);
				V v5 = new V(0.77f, 2.42f, -0.015f);
				V v6 = new V(-0.12f, 2.42f, -0.015f);
				V v7 = new V(-0.11f, 0.76f, -0.015f);
				draft.Face(v4, v7, v6, v5);
				draft.Face(v4 + new V(0f, 0f, 0.03f), v5 + new V(0f, 0f, 0.03f), v6 + new V(0f, 0f, 0.03f), v7 + new V(0f, 0f, 0.03f));
				plan.Add(draft, Surface.Linen, default(V), "rotor", num10);
				plan.Beam(Surface.Wood, func(new V(-0.13f, 2.44f, 0f)), func(new V(0.79f, 2.44f, 0f)), 0.065f, "rotor");
				for (int num11 = 0; num11 < 5; num11++)
				{
					plan.Box(Surface.Iron, func(new V(0.05f + (float)num11 * 0.14f, 2.44f, -0.042f)), new V(0.025f, 0.12f, 0.025f), "rotor", num10);
				}
			}
			plan.Box(Surface.Copper, default(V), new V(0.18f, 0.18f, 0.12f), "dynamo");
			return plan;
		}

		private static void Chain(Plan p, V top, int count)
		{
			for (int i = 0; i < count; i++)
			{
				p.Hoop(top + new V(0f, (float)(-i) * 0.09f, 0f), 0.055f, 0.011f, i % 2 == 0);
			}
		}

		private static void Lantern(Plan p, V center, float scale)
		{
			p.Profile(Surface.Copper, center, 6, new float[3]
			{
				-0.32f * scale,
				-0.29f * scale,
				-0.24f * scale
			}, new float[3]
			{
				0.17f * scale,
				0.3f * scale,
				0.25f * scale
			});
			p.Profile(Surface.Copper, center, 6, new float[4]
			{
				0.24f * scale,
				0.28f * scale,
				0.43f * scale,
				0.47f * scale
			}, new float[4]
			{
				0.26f * scale,
				0.33f * scale,
				0.13f * scale,
				0.08f * scale
			});
			p.Profile(Surface.Iron, center + new V(0f, 0.48f * scale, 0f), 8, new float[2]
			{
				-0.02f * scale,
				0.025f * scale
			}, new float[2]
			{
				0.08f * scale,
				0.06f * scale
			});
			for (int i = 0; i < 6; i++)
			{
				double num = Math.PI * 2.0 * (double)i / 6.0;
				V start = center + new V((float)Math.Cos(num) * 0.21f * scale, -0.24f * scale, (float)Math.Sin(num) * 0.21f * scale);
				V v = center + new V((float)Math.Cos(num) * 0.27f * scale, 0f, (float)Math.Sin(num) * 0.27f * scale);
				V end = center + new V((float)Math.Cos(num) * 0.21f * scale, 0.24f * scale, (float)Math.Sin(num) * 0.21f * scale);
				p.Beam(Surface.Iron, start, v, 0.028f * scale);
				p.Beam(Surface.Iron, v, end, 0.028f * scale);
			}
			p.Bolt(center + new V(0f, -0.274f, -0.253f) * scale, 0.018f * scale);
			p.Bolt(center + new V(0f, 0.29f, -0.29f) * scale, 0.018f * scale);
			float[] heights = new float[4]
			{
				-0.23f * scale,
				-0.15f * scale,
				0.14f * scale,
				0.23f * scale
			};
			float[] array = new float[4]
			{
				0.035f * scale,
				0.1f * scale,
				0.09f * scale,
				0.025f * scale
			};
			p.Profile(Surface.Amber, center, 6, heights, array);
			float[] radii = Array.ConvertAll(array, (float num2) => num2 * 1.04f);
			p.Profile(Surface.Glow, center, 6, heights, radii, "glow");
			p.Light = center;
			p.Colliders.Add(new HitBox
			{
				Position = center,
				Size = new V(0.57f, 0.8f, 0.57f) * scale
			});
		}

		internal static Plan Pendant()
		{
			Plan plan = new Plan();
			plan.Box(Surface.Iron, new V(0f, -0.025f, 0f), new V(0.24f, 0.05f, 0.24f), "static", 0f, solid: true);
			plan.Bolt(new V(0.075f, -0.025f, -0.126f), 0.022f);
			Chain(plan, new V(0f, -0.11f, 0f), 3);
			Lantern(plan, new V(0f, -0.8f, 0f), 1f);
			return plan;
		}

		internal static Plan Wall()
		{
			Plan plan = new Plan();
			plan.Box(Surface.Copper, new V(0f, 0f, 0.04f), new V(0.25f, 0.56f, 0.075f), "static", 0f, solid: true);
			float[] array = new float[2] { -0.075f, 0.075f };
			foreach (float x in array)
			{
				float[] array2 = new float[2] { -0.2f, 0.2f };
				foreach (float y in array2)
				{
					plan.Bolt(new V(x, y, -0.004f));
				}
			}
			V[] array3 = new V[4]
			{
				new V(0f, 0.17f, 0f),
				new V(0f, 0.27f, -0.13f),
				new V(0f, 0.29f, -0.32f),
				new V(0f, 0.22f, -0.48f)
			};
			for (int k = 0; k < array3.Length - 1; k++)
			{
				plan.Beam(Surface.Iron, array3[k], array3[k + 1], 0.055f);
			}
			plan.Beam(Surface.Iron, new V(0f, -0.14f, -0.015f), new V(0f, 0.27f, -0.3f), 0.035f);
			Chain(plan, new V(0f, 0.14f, -0.48f), 1);
			Lantern(plan, new V(0f, -0.4f, -0.48f), 0.88f);
			return plan;
		}

		internal static Plan Garden(float nativeHeight)
		{
			if (float.IsNaN(nativeHeight) || float.IsInfinity(nativeHeight) || nativeHeight < 0.5f || nativeHeight > 8f)
			{
				throw new ArgumentOutOfRangeException("nativeHeight");
			}
			Plan plan = new Plan();
			plan.Box(Surface.Stone, new V(0f, 0.1f, 0f), new V(0.55f, 0.2f, 0.55f), "static", 0f, solid: true);
			plan.Box(Surface.Wood, new V(0f, 1.38f, 0f), new V(0.2f, 2.56f, 0.2f), "static", 0f, solid: true);
			float[] array = new float[3] { 0.3f, 1.95f, 2.55f };
			foreach (float y in array)
			{
				plan.Box(Surface.Copper, new V(0f, y, 0f), new V(0.24f, 0.09f, 0.24f));
				plan.Bolt(new V(0f, y, -0.13f), 0.027f);
			}
			plan.Box(Surface.Wood, new V(0.32f, 2.62f, 0f), new V(0.92f, 0.15f, 0.16f), "static", 0f, solid: true);
			plan.Beam(Surface.Iron, new V(0.02f, 1.98f, 0f), new V(0.62f, 2.55f, 0f), 0.045f);
			Chain(plan, new V(0.66f, 2.5f, 0f), 2);
			Lantern(plan, new V(0.66f, 1.92f, 0f), 0.85f);
			plan.Scale(nativeHeight / plan.StaticHeight);
			return plan;
		}

		internal static Plan Heater()
		{
			Plan plan = new Plan
			{
				IsHeater = true,
				Radius = 4f,
				Intensity = 0.8f
			};
			for (int i = 0; i < 8; i++)
			{
				double num = (double)i * Math.PI / 4.0;
				plan.Box(Surface.Stone, new V((float)Math.Cos(num) * 0.42f, 0.09f, (float)Math.Sin(num) * 0.42f), new V(0.35f, 0.18f + (float)(i % 2) * 0.02f, 0.28f), "static", 0f, solid: true, i * 45);
			}
			plan.Profile(Surface.Iron, new V(0f, 0.2f, 0f), 8, new float[4] { 0f, 0.06f, 0.72f, 0.78f }, new float[4] { 0.37f, 0.41f, 0.41f, 0.37f });
			plan.Profile(Surface.Copper, new V(0f, 0.2f, 0f), 8, new float[3] { 0.025f, 0.045f, 0.11f }, new float[3] { 0.44f, 0.46f, 0.44f });
			plan.Profile(Surface.Copper, new V(0f, 0.2f, 0f), 8, new float[3] { 0.7f, 0.77f, 0.8f }, new float[3] { 0.44f, 0.46f, 0.4f });
			plan.Box(Surface.Iron, new V(0f, 0.6f, -0.405f), new V(0.49f, 0.61f, 0.11f));
			plan.Profile(Surface.Amber, new V(0f, 0.6f, -0.475f), 6, new float[4] { -0.23f, -0.15f, 0.16f, 0.23f }, new float[4] { 0.04f, 0.125f, 0.12f, 0.035f });
			plan.Profile(Surface.Glow, new V(0f, 0.6f, -0.475f), 6, new float[4] { -0.23f, -0.15f, 0.16f, 0.23f }, new float[4] { 0.042f, 0.13f, 0.125f, 0.036f }, "glow");
			for (int j = -2; j <= 2; j++)
			{
				plan.Box(Surface.Iron, new V((float)j * 0.09f, 0.6f, -0.58f), new V(0.028f, 0.55f, 0.035f));
			}
			float[] array = new float[2] { 0.3f, 0.9f };
			foreach (float y in array)
			{
				plan.Box(Surface.Copper, new V(0f, y, -0.495f), new V(0.54f, 0.065f, 0.12f));
				float[] array2 = new float[2] { -0.23f, 0.23f };
				foreach (float x in array2)
				{
					plan.Bolt(new V(x, y, -0.56f), 0.022f);
				}
			}
			plan.Colliders.Add(new HitBox
			{
				Position = new V(0f, 0.58f, -0.04f),
				Size = new V(0.9f, 0.8f, 1.02f)
			});
			plan.Light = new V(0f, 0.65f, -0.65f);
			return plan;
		}
	}
	internal static class ArtPalette
	{
		internal static float[] Pixel(Surface s, int x, int y)
		{
			int num = (x * 73856093) ^ (y * 19349663) ^ ((int)s * 83492791);
			int num2 = num ^ (num << 13);
			int num3 = num2 ^ (num2 >>> 17);
			float num4 = (float)(uint)((num3 ^ (num3 << 5)) & 0x3FF) / 1023f;
			float num5 = 0.92f + num4 * 0.14f;
			float num6;
			float num7;
			float num8;
			switch (s)
			{
			case Surface.Wood:
				num5 = 0.65f + 0.18f * (float)Math.Sin((double)((float)x * 0.7f) + Math.Sin((float)y * 0.07f) * 0.699999988079071) + num4 * 0.16f;
				if (x % 15 == 0)
				{
					num5 *= 0.55f;
				}
				num6 = 0.15f;
				num7 = 0.115f;
				num8 = 0.085f;
				break;
			case Surface.Copper:
				num6 = 0.54f;
				num7 = 0.27f;
				num8 = 0.12f;
				if (Math.Sin((double)x * 0.2) + Math.Sin((double)y * 0.17) + Math.Sin((double)(x + y) * 0.13) < -2.05)
				{
					num6 = 0.28f;
					num7 = 0.3f;
					num8 = 0.21f;
				}
				if ((x * 3 + y) % 39 == 0)
				{
					num5 *= 1.3f;
				}
				break;
			case Surface.Iron:
				num6 = 0.105f;
				num7 = 0.115f;
				num8 = 0.12f;
				break;
			case Surface.Stone:
				num6 = 0.31f;
				num7 = 0.3f;
				num8 = 0.28f;
				num5 = 0.78f + num4 * 0.18f + 0.1f * (float)Math.Sin((double)x * 0.2 + (double)y * 0.13);
				break;
			case Surface.Linen:
				num6 = 0.61f;
				num7 = 0.49f;
				num8 = 0.32f;
				if (x % 8 == 0 || y % 8 == 0)
				{
					num5 *= 0.87f;
				}
				if (x < 2 || y < 2)
				{
					num5 *= 0.7f;
				}
				break;
			case Surface.BlueCore:
				num6 = 0.075f;
				num7 = 0.25f;
				num8 = 0.43f;
				break;
			case Surface.BlueGlow:
				num6 = 0.28f;
				num7 = 0.65f;
				num8 = 1f;
				break;
			case Surface.GreenCore:
				num6 = 0.13f;
				num7 = 0.38f;
				num8 = 0.07f;
				break;
			case Surface.GreenGlow:
				num6 = 0.35f;
				num7 = 1f;
				num8 = 0.3f;
				break;
			case Surface.Amber:
				num6 = 0.48f;
				num7 = 0.23f;
				num8 = 0.055f;
				break;
			default:
				num6 = 1f;
				num7 = 0.56f