Decompiled source of EternalMeteor v1.2.3

plugins/EternalMeteor.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EternalMeteor.Commands;
using EternalMeteor.Items;
using EternalMeteor.Logic;
using EternalMeteor.Meteor;
using EternalMeteor.Protection;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("EternalMeteor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: AssemblyInformationalVersion("1.2.3")]
[assembly: AssemblyProduct("EternalMeteor")]
[assembly: AssemblyTitle("EternalMeteor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EternalMeteor
{
	internal static class AssetLoader
	{
		private static readonly MethodInfo s_setAudioData = typeof(AudioClip).GetMethod("SetData", new Type[2]
		{
			typeof(float[]),
			typeof(int)
		});

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

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

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

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

		private static string s_root;

		internal static void Init(string pluginDirectory)
		{
			s_root = Path.Combine(pluginDirectory, "Assets");
		}

		internal static Texture2D Texture(string relativePath, bool linear, bool normalMap, FilterMode filter)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (s_textures.TryGetValue(relativePath, out var value))
			{
				return value;
			}
			byte[] array = ReadFile(relativePath);
			if (array == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!AssetUtils.LoadImage(val, array))
			{
				Log.Error("Assets", relativePath + " is not a valid image");
				Object.Destroy((Object)(object)val);
				return null;
			}
			Texture2D val2 = val;
			if (linear || normalMap)
			{
				Color32[] pixels = val.GetPixels32();
				if (normalMap)
				{
					PackNormals(pixels);
				}
				val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, true, true);
				val2.SetPixels32(pixels);
				Object.Destroy((Object)(object)val);
			}
			((Object)val2).name = "EternalMeteor_" + Path.GetFileNameWithoutExtension(relativePath);
			((Texture)val2).wrapMode = (TextureWrapMode)0;
			((Texture)val2).filterMode = filter;
			((Texture)val2).anisoLevel = 1;
			val2.Apply(true, false);
			val2.Compress(true);
			val2.Apply(false, true);
			s_textures[relativePath] = val2;
			Log.Info("Assets", string.Format("{0}: {1}x{2} {3} {4}", relativePath, ((Texture)val2).width, ((Texture)val2).height, (linear || normalMap) ? "linear" : "sRGB", val2.format));
			return val2;
		}

		internal static Sprite Sprite(string relativePath)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00a2: 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)
			if (s_sprites.TryGetValue(relativePath, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			byte[] array = ReadFile(relativePath);
			if (array == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!AssetUtils.LoadImage(val, array))
			{
				Log.Error("Assets", relativePath + " is not a valid image");
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Object)val).name = "EternalMeteor_" + Path.GetFileNameWithoutExtension(relativePath);
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply(false, true);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height);
			Sprite val3 = Sprite.Create(val, val2, new Vector2(0.5f, 0.5f), 100f);
			s_sprites[relativePath] = val3;
			return val3;
		}

		internal static AudioClip Clip(string relativePath)
		{
			if (s_clips.TryGetValue(relativePath, out var value))
			{
				return value;
			}
			byte[] array = ReadFile(relativePath);
			if (array == null)
			{
				return null;
			}
			try
			{
				AudioClip val = ParseWav(Path.GetFileNameWithoutExtension(relativePath), array);
				s_clips[relativePath] = val;
				Log.Info("Assets", $"{relativePath}: {val.length:0.00} s, {val.channels} ch, {val.frequency} Hz");
				return val;
			}
			catch (Exception ex)
			{
				Log.Error("Assets", relativePath + " could not be read: " + ex.Message);
				return null;
			}
		}

		internal static Mesh Mesh(string relativePath)
		{
			if (s_meshes.TryGetValue(relativePath, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string text = Path.Combine(s_root, relativePath);
			if (!File.Exists(text))
			{
				Log.Error("Assets", "missing file " + text);
				return null;
			}
			try
			{
				Mesh val = ParseObj(Path.GetFileNameWithoutExtension(relativePath), File.ReadAllLines(text));
				s_meshes[relativePath] = val;
				Log.Info("Assets", $"{relativePath}: {val.vertexCount} vertices, {val.triangles.Length / 3} triangles");
				return val;
			}
			catch (Exception ex)
			{
				Log.Error("Assets", relativePath + " could not be read: " + ex.Message);
				return null;
			}
		}

		private static Mesh ParseObj(string name, string[] lines)
		{
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: 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)
			List<Vector3> list = new List<Vector3>();
			List<Vector2> list2 = new List<Vector2>();
			List<Vector3> list3 = new List<Vector3>();
			List<Vector3> list4 = new List<Vector3>();
			List<Vector2> list5 = new List<Vector2>();
			List<Vector3> list6 = new List<Vector3>();
			List<int> list7 = new List<int>();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			List<int> list8 = new List<int>();
			char[] separator = new char[2] { ' ', '\t' };
			for (int i = 0; i < lines.Length; i++)
			{
				string[] array = lines[i].Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length == 0)
				{
					continue;
				}
				switch (array[0])
				{
				case "v":
					list.Add(new Vector3(Number(array[1]), Number(array[2]), Number(array[3])));
					break;
				case "vt":
					list2.Add(new Vector2(Number(array[1]), Number(array[2])));
					break;
				case "vn":
					list3.Add(new Vector3(Number(array[1]), Number(array[2]), Number(array[3])));
					break;
				case "f":
				{
					list8.Clear();
					for (int j = 1; j < array.Length; j++)
					{
						if (!dictionary.TryGetValue(array[j], out var value))
						{
							string[] array2 = array[j].Split(new char[1] { '/' });
							value = list4.Count;
							list4.Add(list[int.Parse(array2[0], CultureInfo.InvariantCulture) - 1]);
							list5.Add((array2.Length > 1 && array2[1].Length > 0) ? list2[int.Parse(array2[1], CultureInfo.InvariantCulture) - 1] : Vector2.zero);
							list6.Add((array2.Length > 2 && array2[2].Length > 0) ? list3[int.Parse(array2[2], CultureInfo.InvariantCulture) - 1] : Vector3.up);
							dictionary[array[j]] = value;
						}
						list8.Add(value);
					}
					for (int k = 1; k + 1 < list8.Count; k++)
					{
						list7.Add(list8[0]);
						list7.Add(list8[k]);
						list7.Add(list8[k + 1]);
					}
					break;
				}
				}
			}
			if (list7.Count == 0)
			{
				throw new InvalidDataException("no faces");
			}
			Mesh val = new Mesh
			{
				name = name
			};
			if (list4.Count > 65000)
			{
				val.indexFormat = (IndexFormat)1;
			}
			val.vertices = list4.ToArray();
			val.uv = list5.ToArray();
			val.normals = list6.ToArray();
			val.triangles = list7.ToArray();
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
		}

		private static float Number(string text)
		{
			return float.Parse(text, NumberStyles.Float, CultureInfo.InvariantCulture);
		}

		private static byte[] ReadFile(string relativePath)
		{
			string text = Path.Combine(s_root, relativePath);
			if (!File.Exists(text))
			{
				Log.Error("Assets", "missing file " + text);
				return null;
			}
			return File.ReadAllBytes(text);
		}

		private static void PackNormals(Color32[] pixels)
		{
			//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_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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < pixels.Length; i++)
			{
				Color32 val = pixels[i];
				pixels[i] = new Color32(byte.MaxValue, val.g, val.g, val.r);
			}
		}

		private static AudioClip ParseWav(string name, byte[] data)
		{
			if (data.Length < 12 || Encoding.ASCII.GetString(data, 0, 4) != "RIFF" || Encoding.ASCII.GetString(data, 8, 4) != "WAVE")
			{
				throw new InvalidDataException("not a RIFF/WAVE file");
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = -1;
			int num5 = 0;
			int num6 = 12;
			while (num6 + 8 <= data.Length)
			{
				string text = Encoding.ASCII.GetString(data, num6, 4);
				int num7 = BitConverter.ToInt32(data, num6 + 4);
				int num8 = num6 + 8;
				if (text == "fmt ")
				{
					if (BitConverter.ToInt16(data, num8) != 1)
					{
						throw new InvalidDataException("only uncompressed PCM is supported");
					}
					num = BitConverter.ToInt16(data, num8 + 2);
					num2 = BitConverter.ToInt32(data, num8 + 4);
					num3 = BitConverter.ToInt16(data, num8 + 14);
				}
				else if (text == "data")
				{
					num4 = num8;
					num5 = Math.Min(num7, data.Length - num8);
				}
				num6 = num8 + num7 + (num7 & 1);
			}
			if (num3 != 16 || num < 1 || num2 <= 0 || num4 < 0)
			{
				throw new InvalidDataException($"expected 16-bit PCM, got {num3} bit, {num} channels");
			}
			int num9 = num5 / 2;
			float[] array = new float[num9];
			for (int i = 0; i < num9; i++)
			{
				array[i] = (float)BitConverter.ToInt16(data, num4 + i * 2) / 32768f;
			}
			AudioClip val = AudioClip.Create(name, num9 / num, num, num2, false);
			s_setAudioData.Invoke(val, new object[2] { array, 0 });
			return val;
		}
	}
	internal static class ConfigManager
	{
		private const string MeteorSection = "1 - Meteors";

		private const string ImpactSection = "2 - Impact";

		private const string RockSection = "3 - Meteorite";

		private const string ProtectionSection = "4 - Protection stone";

		private const string EffectsSection = "5 - Effects";

		private const string DebugSection = "6 - Debug";

		private const string WeaponsSection = "7 - Strange weapons";

		private const string ArmourSection = "8 - Strange armor";

		internal static ConfigEntry<bool> RandomMeteors;

		internal static ConfigEntry<float> MinIntervalMinutes;

		internal static ConfigEntry<float> MaxIntervalMinutes;

		internal static ConfigEntry<float> MinDistance;

		internal static ConfigEntry<float> MaxDistance;

		internal static ConfigEntry<float> FallSeconds;

		internal static ConfigEntry<bool> AllowOcean;

		internal static ConfigEntry<bool> MapPins;

		internal static ConfigEntry<float> ImpactRadius;

		internal static ConfigEntry<bool> KillPlayers;

		internal static ConfigEntry<bool> KillBosses;

		internal static ConfigEntry<bool> DestroyBuildings;

		internal static ConfigEntry<bool> BuildingsDropResources;

		internal static ConfigEntry<bool> DestroyNature;

		internal static ConfigEntry<float> CraterRadius;

		internal static ConfigEntry<float> CraterDepth;

		internal static ConfigEntry<float> CraterBurnSeconds;

		internal static ConfigEntry<float> MaterialChance;

		internal static ConfigEntry<string> Materials;

		internal static ConfigEntry<bool> FollowProgression;

		internal static ConfigEntry<int> MinPickaxeTier;

		internal static ConfigEntry<float> RockHealth;

		internal static ConfigEntry<float> StrangeOreChance;

		internal static ConfigEntry<int> StrangeOreMin;

		internal static ConfigEntry<int> StrangeOreMax;

		internal static ConfigEntry<string> StrangeOreKey;

		internal static ConfigEntry<float> ProtectionRadius;

		internal static ConfigEntry<float> BounceMargin;

		internal static ConfigEntry<int> StoneAmount;

		internal static ConfigEntry<int> FineWoodAmount;

		internal static ConfigEntry<int> CopperAmount;

		internal static ConfigEntry<bool> CameraShake;

		internal static ConfigEntry<bool> ScreenFlash;

		internal static ConfigEntry<float> Volume;

		internal static ConfigEntry<int> DebrisCount;

		internal static ConfigEntry<bool> AlwaysShowDome;

		internal static ConfigEntry<bool> WeaponLightning;

		internal static ConfigEntry<bool> VerboseLogging;

		internal static ConfigEntry<float> CrossbowPierce;

		internal static ConfigEntry<float> CrossbowPiercePerLevel;

		internal static ConfigEntry<float> CrossbowFreeShotChance;

		internal static ConfigEntry<int> CrossbowMaxFreeShots;

		internal static ConfigEntry<float> CrossbowBleedChance;

		internal static ConfigEntry<string> CrossbowRecipe;

		internal static ConfigEntry<float> BowPierce;

		internal static ConfigEntry<float> BowPiercePerLevel;

		internal static ConfigEntry<float> BowFreeShotChance;

		internal static ConfigEntry<int> BowMaxFreeShots;

		internal static ConfigEntry<float> BowBleedChance;

		internal static ConfigEntry<string> BowRecipe;

		internal static ConfigEntry<float> BleedSeconds;

		internal static ConfigEntry<float> BleedPercentPerSecond;

		internal static ConfigEntry<float> BleedBossDamagePerSecond;

		internal static ConfigEntry<float> TrophyChance;

		internal static ConfigEntry<float> RunestoneChance;

		internal static ConfigEntry<string> Runestones;

		internal static ConfigEntry<float> ArmourPerPiece;

		internal static ConfigEntry<float> ArmourPerLevel;

		internal static ConfigEntry<float> SetArmourBonus;

		internal static ConfigEntry<float> SetStaminaRegenBonus;

		internal static ConfigEntry<float> SetRunJumpStaminaReduction;

		internal static ConfigEntry<float> SetHealthRegenBonus;

		internal static ConfigEntry<bool> SetAntiFreezing;

		internal static ConfigEntry<float> SetFrostReduction;

		internal static ConfigEntry<float> ReflectFraction;

		internal static ConfigEntry<float> ReflectCooldownSeconds;

		internal static ConfigEntry<float> SoulTouchChance;

		internal static ConfigEntry<float> SoulMarkSeconds;

		internal static ConfigEntry<float> SoulMarkDamageBonus;

		internal static ConfigEntry<float> SoulTouchCooldownSeconds;

		internal static ConfigEntry<string> HelmetRecipe;

		internal static ConfigEntry<string> ChestRecipe;

		internal static ConfigEntry<string> LegsRecipe;

		internal static void Bind(ConfigFile config)
		{
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Expected O, but got Unknown
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Expected O, but got Unknown
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Expected O, but got Unknown
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Expected O, but got Unknown
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Expected O, but got Unknown
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Expected O, but got Unknown
			Version savedBy = ConfigMigration.SavedBy(FirstLine(config.ConfigFilePath));
			RandomMeteors = AdminBool(config, "1 - Meteors", "RandomMeteors", value: true, "Meteors fall on their own near the players. Off leaves only the console commands.");
			MinIntervalMinutes = Admin(config, "1 - Meteors", "MinIntervalMinutes", 30f, 1f, 1440f, "Shortest time between two random meteors, in real minutes.");
			MaxIntervalMinutes = Admin(config, "1 - Meteors", "MaxIntervalMinutes", 30f, 1f, 1440f, "Longest time between two random meteors, in real minutes. The same as the shortest makes the interval fixed.");
			MinDistance = Admin(config, "1 - Meteors", "MinDistance", 80f, 0f, 2000f, "A random meteor lands at least this far from the player it was aimed near, in metres.");
			MaxDistance = Admin(config, "1 - Meteors", "MaxDistance", 500f, 10f, 3000f, "A random meteor lands at most this far from the player it was aimed near, in metres.");
			FallSeconds = Admin(config, "1 - Meteors", "FallSeconds", 15f, 5f, 60f, "Seconds from the first flash in the sky to the impact: the warning time to run.");
			AllowOcean = AdminBool(config, "1 - Meteors", "AllowOcean", value: false, "Random meteors may land in the sea. Off makes them look for dry land.");
			MapPins = AdminBool(config, "1 - Meteors", "MapPins", value: true, "Every meteor crater and every meteorite not yet mined is marked on every player's map, also for players who join later.");
			ImpactRadius = Admin(config, "2 - Impact", "Radius", 25f, 5f, 100f, "Radius of destruction in metres (25 = a circle 50 m wide). Everything alive dies and everything built is destroyed.");
			KillPlayers = AdminBool(config, "2 - Impact", "KillPlayers", value: true, "Players caught in the impact die.");
			KillBosses = AdminBool(config, "2 - Impact", "KillBosses", value: false, "Bosses caught in the impact die too.");
			DestroyBuildings = AdminBool(config, "2 - Impact", "DestroyBuildings", value: true, "Build pieces (houses, ships, portals, wards...) caught in the impact are destroyed.");
			BuildingsDropResources = AdminBool(config, "2 - Impact", "BuildingsDropResources", value: false, "Destroyed build pieces drop their materials. Off by default: a base would turn into a lag-inducing pile of items. Chests always spill what they hold.");
			DestroyNature = AdminBool(config, "2 - Impact", "DestroyNature", value: true, "Trees, logs, rocks, ore deposits and bushes caught in the impact are destroyed.");
			CraterRadius = Admin(config, "2 - Impact", "CraterRadius", 12f, 0f, 30f, "Radius of the crater in metres. 0 leaves the ground as it was.");
			CraterDepth = Admin(config, "2 - Impact", "CraterDepth", 4f, 0f, 8f, "Depth of the crater in metres at its centre.");
			CraterBurnSeconds = Admin(config, "2 - Impact", "CraterBurnSeconds", 60f, 0f, 600f, "Seconds the crater keeps burning after the impact; the meteorite cools down in the same time. 0 leaves no fire.");
			MaterialChance = Admin(config, "3 - Meteorite", "MaterialChance", 0.3f, 0f, 1f, "Chance for each material to be in a meteorite (0.3 = 30 %). At least one is always there.");
			Materials = config.Bind<string>("3 - Meteorite", "Materials", "CopperOre:20:30:;TinOre:20:30:;Bronze:8:15:;IronScrap:20:30:defeated_gdking;SilverOre:15:25:defeated_bonemass;BlackMetalScrap:15:25:defeated_dragon;FlametalOreNew:10:20:defeated_queen", new ConfigDescription("Materials a meteorite can carry: ItemPrefab:min:max:requiredGlobalKey, separated by ';'. The key (a boss kill) is only checked when FollowProgression is on; leave it empty for always.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			FollowProgression = AdminBool(config, "3 - Meteorite", "FollowProgression", value: true, "Materials only appear once their boss is defeated (iron after The Elder, silver after Bonemass, black metal after Moder, flametal after The Queen).");
			MinPickaxeTier = AdminInt(config, "3 - Meteorite", "MinPickaxeTier", 0, 0, 5, "Pickaxe tier needed to mine a meteorite (0 = stone or antler pickaxe, 1 = bronze, 2 = iron, 3 = black metal).");
			RockHealth = Admin(config, "3 - Meteorite", "Health", 300f, 10f, 5000f, "How many pickaxe hits' worth of health a meteorite has.");
			StrangeOreChance = Admin(config, "3 - Meteorite", "StrangeOreChance", 0.4f, 0f, 1f, "Share of meteorites that carry Strange ore, on top of their other materials (0.4 = 40 %). New meteors bring it at regular steps: with 0.4, every 2 or 3 meteors. A meteorite that fell before this version gets this chance once, when a player first comes near it.");
			StrangeOreMin = AdminInt(config, "3 - Meteorite", "StrangeOreMin", 10, 0, 100, "Fewest pieces of Strange ore in a meteorite that carries it.");
			StrangeOreMax = AdminInt(config, "3 - Meteorite", "StrangeOreMax", 15, 0, 100, "Most pieces of Strange ore in a meteorite that carries it. 0 leaves Strange ore out of meteorites.");
			StrangeOreKey = config.Bind<string>("3 - Meteorite", "StrangeOreKey", "defeated_dragon", new ConfigDescription("Boss key that unlocks Strange ore in meteorites when FollowProgression is on (defeated_dragon = after Moder). Empty for always. A meteor called with meteorshow while devcommands is on skips it.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			ProtectionRadius = Admin(config, "4 - Protection stone", "Radius", 60f, 10f, 200f, "Radius protected by an EternalMeteor stone, in metres (60 = a circle 120 m wide).");
			BounceMargin = Admin(config, "4 - Protection stone", "BounceDistance", 8f, 2f, 100f, "A meteor bounced by a dome lands this many metres past its edge, and always beyond the crater radius, so its crater never digs under the dome.");
			StoneAmount = AdminInt(config, "4 - Protection stone", "Stone", 10, 0, 999, "Stone needed to build the protection stone.");
			FineWoodAmount = AdminInt(config, "4 - Protection stone", "FineWood", 5, 0, 999, "Fine wood needed to build the protection stone.");
			CopperAmount = AdminInt(config, "4 - Protection stone", "Copper", 4, 0, 999, "Copper needed to build the protection stone.");
			CameraShake = config.Bind<bool>("5 - Effects", "CameraShake", true, "The camera shakes as a meteor comes down and lands.");
			ScreenFlash = config.Bind<bool>("5 - Effects", "ScreenFlash", true, "A white flash when a meteor lands close to you.");
			Volume = config.Bind<float>("5 - Effects", "Volume", 1f, new ConfigDescription("Volume of the meteor sounds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			DebrisCount = config.Bind<int>("5 - Effects", "Debris", 18, new ConfigDescription("Burning rocks thrown by an impact.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			AlwaysShowDome = config.Bind<bool>("5 - Effects", "AlwaysShowDome", false, "Show the protection domes all the time. Off shows them only for a few seconds after a meteor hits them.");
			WeaponLightning = config.Bind<bool>("5 - Effects", "WeaponLightning", true, "Red lightning crackles over a loaded Strange crossbow and a drawn Strange bow.");
			VerboseLogging = config.Bind<bool>("6 - Debug", "VerboseLogging", false, "Log extra detail, such as every object an impact destroys.");
			BindWeapons(config);
			BindArmour(config);
			MoveOldDefaults(savedBy);
			SynchronizationManager.OnConfigurationSynchronized += delegate(object sender, ConfigurationSynchronizationEventArgs args)
			{
				Log.Info("Config", args.InitialSynchronization ? "received the server's settings" : "server settings updated");
			};
		}

		internal static List<LootMaterial> ParsedMaterials()
		{
			List<string> list = new List<string>();
			List<LootMaterial> result = MeteorLoot.ParseMaterials(Materials.Value, list);
			foreach (string item in list)
			{
				Log.Warning("Config", "ignored material entry \"" + item + "\" (expected ItemPrefab:min:max:key)");
			}
			return result;
		}

		internal static List<RecipePart> ParsedRecipe(ConfigEntry<string> recipe)
		{
			List<string> list = new List<string>();
			List<RecipePart> result = ItemRecipe.Parse(recipe.Value, list);
			foreach (string item in list)
			{
				Log.Warning("Config", "ignored " + ((ConfigEntryBase)recipe).Definition.Key + " entry \"" + item + "\" (expected ItemPrefab:amount:amountPerLevel)");
			}
			return result;
		}

		private static void BindWeapons(ConfigFile config)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Expected O, but got Unknown
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Expected O, but got Unknown
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Expected O, but got Unknown
			CrossbowPierce = Admin(config, "7 - Strange weapons", "CrossbowPierce", 180f, 1f, 1000f, "Pierce damage of the Strange crossbow, before its bolt's.");
			CrossbowPiercePerLevel = Admin(config, "7 - Strange weapons", "CrossbowPiercePerLevel", 4f, 0f, 100f, "Pierce damage the Strange crossbow gains with each upgrade.");
			CrossbowFreeShotChance = Admin(config, "7 - Strange weapons", "CrossbowFreeShotChance", 0.6f, 0f, 1f, "Chance that a crossbow shot spends no bolt and leaves the crossbow loaded (0.6 = 60 %).");
			CrossbowMaxFreeShots = AdminInt(config, "7 - Strange weapons", "CrossbowMaxFreeShots", 2, 0, 10, "Most free crossbow shots in a row: with 2, one load fires at most 3 bolts.");
			CrossbowBleedChance = Admin(config, "7 - Strange weapons", "CrossbowBleedChance", 0.6f, 0f, 1f, "Chance that a crossbow hit makes its target bleed (0.6 = 60 %).");
			CrossbowRecipe = config.Bind<string>("7 - Strange weapons", "CrossbowRecipe", "EternalMeteor_StrangeIngot:80:40;FineWood:10:5;Silver:6:3;WolfPelt:4:2", new ConfigDescription("Strange crossbow recipe at a level 3 forge: ItemPrefab:amount:amountPerLevel separated by ';'. The second number is the cost of each upgrade.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			BowPierce = Admin(config, "7 - Strange weapons", "BowPierce", 60f, 1f, 1000f, "Pierce damage of the Strange bow, before its arrow's.");
			BowPiercePerLevel = Admin(config, "7 - Strange weapons", "BowPiercePerLevel", 3f, 0f, 100f, "Pierce damage the Strange bow gains with each upgrade.");
			BowFreeShotChance = Admin(config, "7 - Strange weapons", "BowFreeShotChance", 0.6f, 0f, 1f, "Chance that a bow shot spends no arrow (0.6 = 60 %).");
			BowMaxFreeShots = AdminInt(config, "7 - Strange weapons", "BowMaxFreeShots", 2, 0, 10, "Most free bow shots in a row.");
			BowBleedChance = Admin(config, "7 - Strange weapons", "BowBleedChance", 0.6f, 0f, 1f, "Chance that a bow hit makes its target bleed (0.6 = 60 %).");
			BowRecipe = config.Bind<string>("7 - Strange weapons", "BowRecipe", "EternalMeteor_StrangeIngot:80:40;FineWood:8:4;Silver:4:2;WolfPelt:2:1", new ConfigDescription("Strange bow recipe at a level 3 forge, written as CrossbowRecipe.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			BleedSeconds = Admin(config, "7 - Strange weapons", "BleedSeconds", 10f, 1f, 60f, "Seconds a bleeding lasts. A bleeding target cannot start bleeding again until it ends.");
			BleedPercentPerSecond = Admin(config, "7 - Strange weapons", "BleedPercentPerSecond", 1.5f, 0f, 20f, "Share of its maximum health a bleeding creature or player loses every second, in % (1.5 = 15 % over 10 s).");
			BleedBossDamagePerSecond = Admin(config, "7 - Strange weapons", "BleedBossDamagePerSecond", 1.5f, 0f, 100f, "Damage a bleeding boss takes every second, a flat amount.");
			TrophyChance = Admin(config, "7 - Strange weapons", "TrophyChance", 0.5f, 0f, 1f, "A creature killed by the Strange crossbow or bow, or by their bleeding, drops its head (trophy) with at least this chance (0.5 = 50 %). Creatures whose own chance is higher keep it.");
			RunestoneChance = Admin(config, "7 - Strange weapons", "RunestoneChance", 0.35f, 0f, 1f, "Chance that a creature killed by the Strange crossbow or bow, or by their bleeding, drops one Epic Loot runestone (0.35 = 35 %). Needs Epic Loot; without it no runestone drops and everything else works the same.");
			Runestones = config.Bind<string>("7 - Strange weapons", "Runestones", "RunestoneMagic:40;RunestoneRare:28;RunestoneEpic:17;RunestoneLegendary:9;RunestoneMythic:4;RunestoneAncient:2", new ConfigDescription("Which runestone drops and how often: ItemPrefab:weight separated by ';' (by default Magic 40, Rare 28, Epic 17, Legendary 9, Mythic 4, Ancient 2). Prefabs this game does not have are left out.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private static void BindArmour(ConfigFile config)
		{
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Expected O, but got Unknown
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Expected O, but got Unknown
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Expected O, but got Unknown
			ArmourPerPiece = Admin(config, "8 - Strange armor", "ArmorPerPiece", 25f, 0f, 200f, "Armor of each Strange piece (helmet, breastplate, greaves), as the silver armor.");
			ArmourPerLevel = Admin(config, "8 - Strange armor", "ArmorPerLevel", 2f, 0f, 50f, "Armor each piece gains with each upgrade.");
			SetArmourBonus = Admin(config, "8 - Strange armor", "SetArmorBonus", 0.1f, 0f, 1f, "With the three pieces on: extra armor (0.1 = +10 %).");
			SetStaminaRegenBonus = Admin(config, "8 - Strange armor", "SetStaminaRegenBonus", 0.15f, 0f, 1f, "With the three pieces on: faster stamina regeneration (0.15 = +15 %).");
			SetRunJumpStaminaReduction = Admin(config, "8 - Strange armor", "SetRunJumpStaminaReduction", 0.15f, 0f, 1f, "With the three pieces on: less stamina spent running and jumping (0.15 = -15 %).");
			SetHealthRegenBonus = Admin(config, "8 - Strange armor", "SetHealthRegenBonus", 0.15f, 0f, 1f, "With the three pieces on: faster health regeneration (0.15 = +15 %).");
			SetAntiFreezing = AdminBool(config, "8 - Strange armor", "SetAntiFreezing", value: true, "With the three pieces on: the cold of mountains and nights never freezes you.");
			SetFrostReduction = Admin(config, "8 - Strange armor", "SetFrostReduction", 0.15f, 0f, 1f, "With the three pieces on: less frost damage (0.15 = -15 %), on top of any other frost resistance.");
			ReflectFraction = Admin(config, "8 - Strange armor", "ReflectFraction", 0.25f, 0f, 1f, "With the three pieces on: the next hit you take sends this share of its damage back to the attacker (0.25 = 25 %). You still take the hit.");
			ReflectCooldownSeconds = Admin(config, "8 - Strange armor", "ReflectCooldownSeconds", 300f, 1f, 3600f, "Seconds before the armor reflects a hit again.");
			SoulTouchChance = Admin(config, "8 - Strange armor", "SoulTouchChance", 0.4f, 0f, 1f, "With the three pieces on: chance that a hit does nothing to you and marks its attacker (0.4 = 40 %).");
			SoulMarkSeconds = Admin(config, "8 - Strange armor", "SoulMarkSeconds", 5f, 1f, 60f, "Seconds the soul mark stays on the attacker.");
			SoulMarkDamageBonus = Admin(config, "8 - Strange armor", "SoulMarkDamageBonus", 0.15f, 0f, 2f, "Extra damage a marked attacker takes from everything (0.15 = +15 %).");
			SoulTouchCooldownSeconds = Admin(config, "8 - Strange armor", "SoulTouchCooldownSeconds", 300f, 1f, 3600f, "Seconds before the soul touch can happen again.");
			HelmetRecipe = config.Bind<string>("8 - Strange armor", "HelmetRecipe", "EternalMeteor_StrangeIngot:80:40;Silver:3:2;WolfPelt:2:1", new ConfigDescription("Strange helmet recipe at a level 3 forge: ItemPrefab:amount:amountPerLevel separated by ';'.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			ChestRecipe = config.Bind<string>("8 - Strange armor", "ChestRecipe", "EternalMeteor_StrangeIngot:80:40;Silver:5:3;WolfPelt:4:2", new ConfigDescription("Strange chest recipe, written as HelmetRecipe.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			LegsRecipe = config.Bind<string>("8 - Strange armor", "LegsRecipe", "EternalMeteor_StrangeIngot:80:40;Silver:4:2;WolfPelt:3:2", new ConfigDescription("Strange legs recipe, written as HelmetRecipe.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private static void MoveOldDefaults(Version savedBy)
		{
			MoveStrangeGearDefaults(savedBy);
			if (ConfigMigration.MovesInterval(savedBy, MinIntervalMinutes.Value, MaxIntervalMinutes.Value))
			{
				MinIntervalMinutes.Value = (float)((ConfigEntryBase)MinIntervalMinutes).DefaultValue;
				MaxIntervalMinutes.Value = (float)((ConfigEntryBase)MaxIntervalMinutes).DefaultValue;
				Log.Info("Config", $"config from v{savedBy} still had the old meteor interval: MinIntervalMinutes 40 -> " + $"{MinIntervalMinutes.Value:0}, MaxIntervalMinutes 90 -> {MaxIntervalMinutes.Value:0}");
			}
		}

		private static void MoveStrangeGearDefaults(Version savedBy)
		{
			List<string> list = new List<string>();
			Version strangeGearChanged = ConfigMigration.StrangeGearChanged;
			Move(ArmourPerPiece, 20f, strangeGearChanged, savedBy, list);
			Move(BowPierce, 54f, strangeGearChanged, savedBy, list);
			Move(CrossbowPierce, 130f, strangeGearChanged, savedBy, list);
			Move(CrossbowRecipe, "EternalMeteor_StrangeIngot:12:6;FineWood:10:5;Silver:6:3;WolfPelt:4:2", strangeGearChanged, savedBy, list);
			Move(BowRecipe, "EternalMeteor_StrangeIngot:10:5;FineWood:8:4;Silver:4:2;WolfPelt:2:1", strangeGearChanged, savedBy, list);
			Move(HelmetRecipe, "EternalMeteor_StrangeIngot:8:4;Silver:3:2;WolfPelt:2:1", strangeGearChanged, savedBy, list);
			Move(ChestRecipe, "EternalMeteor_StrangeIngot:15:8;Silver:5:3;WolfPelt:4:2", strangeGearChanged, savedBy, list);
			Move(LegsRecipe, "EternalMeteor_StrangeIngot:12:6;Silver:4:2;WolfPelt:3:2", strangeGearChanged, savedBy, list);
			Version recipesRaised = ConfigMigration.RecipesRaised;
			Move(CrossbowRecipe, "EternalMeteor_StrangeIngot:45:23;FineWood:10:5;Silver:6:3;WolfPelt:4:2", recipesRaised, savedBy, list);
			Move(BowRecipe, "EternalMeteor_StrangeIngot:35:18;FineWood:8:4;Silver:4:2;WolfPelt:2:1", recipesRaised, savedBy, list);
			Move(HelmetRecipe, "EternalMeteor_StrangeIngot:30:15;Silver:3:2;WolfPelt:2:1", recipesRaised, savedBy, list);
			Move(ChestRecipe, "EternalMeteor_StrangeIngot:30:15;Silver:5:3;WolfPelt:4:2", recipesRaised, savedBy, list);
			Move(LegsRecipe, "EternalMeteor_StrangeIngot:30:15;Silver:4:2;WolfPelt:3:2", recipesRaised, savedBy, list);
			if (ConfigMigration.MovesStrangeDefault(savedBy, StrangeOreMin.Value, 6) && ConfigMigration.MovesStrangeDefault(savedBy, StrangeOreMax.Value, 10))
			{
				StrangeOreMin.Value = (int)((ConfigEntryBase)StrangeOreMin).DefaultValue;
				StrangeOreMax.Value = (int)((ConfigEntryBase)StrangeOreMax).DefaultValue;
				list.Add($"StrangeOreMin/Max {6}-{10} -> {StrangeOreMin.Value}-{StrangeOreMax.Value}");
			}
			if (ConfigMigration.MovesDefault(savedBy, ConfigMigration.StrangeOreKeyChanged, StrangeOreKey.Value, "defeated_bonemass"))
			{
				StrangeOreKey.Value = (string)((ConfigEntryBase)StrangeOreKey).DefaultValue;
				list.Add("StrangeOreKey defeated_bonemass -> " + StrangeOreKey.Value);
			}
			if (list.Count > 0)
			{
				Log.Info("Config", string.Format("config from v{0} still had the Strange gear defaults of a test build: {1}", savedBy, string.Join("; ", list)));
			}
		}

		private static void Move<T>(ConfigEntry<T> entry, T oldDefault, Version changedIn, Version savedBy, List<string> moved)
		{
			if (ConfigMigration.MovesDefault(savedBy, changedIn, entry.Value, oldDefault))
			{
				entry.Value = (T)((ConfigEntryBase)entry).DefaultValue;
				moved.Add($"{((ConfigEntryBase)entry).Definition.Key} {oldDefault} -> {entry.Value}");
			}
		}

		internal static List<KeyValuePair<string, float>> ParsedRunestones()
		{
			List<string> list = new List<string>();
			List<KeyValuePair<string, float>> result = HunterLoot.ParseWeights(Runestones.Value, list);
			foreach (string item in list)
			{
				Log.Warning("Config", "ignored Runestones entry \"" + item + "\" (expected ItemPrefab:weight)");
			}
			return result;
		}

		private static string FirstLine(string path)
		{
			if (!File.Exists(path))
			{
				return null;
			}
			return File.ReadLines(path).FirstOrDefault();
		}

		private static ConfigEntry<float> Admin(ConfigFile config, string section, string key, float value, float min, float max, string description)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			return config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private static ConfigEntry<int> AdminInt(ConfigFile config, string section, string key, int value, int min, int max, string description)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			return config.Bind<int>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private static ConfigEntry<bool> AdminBool(ConfigFile config, string section, string key, bool value, string description)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			return config.Bind<bool>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}
	}
	[BepInPlugin("com.srcodex.eternalmeteor", "EternalMeteor", "1.2.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class EternalMeteorPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.srcodex.eternalmeteor";

		public const string ModName = "EternalMeteor";

		public const string Version = "1.2.3";

		private Harmony _harmony;

		internal static EternalMeteorPlugin Instance { get; private set; }

		internal static bool IsHeadless { get; private set; }

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			IsHeadless = (int)SystemInfo.graphicsDeviceType == 4;
			ConfigManager.Bind(((BaseUnityPlugin)this).Config);
			AssetLoader.Init(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			MeteorPrefabs.Register();
			ProtectionPiece.Register();
			StrangeItems.Register(((BaseUnityPlugin)this).Config);
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new MeteorShowCommand());
			((Component)this).gameObject.AddComponent<MeteorDirector>();
			if (!IsHeadless)
			{
				((Component)this).gameObject.AddComponent<DomeVisual>();
				((Component)this).gameObject.AddComponent<MeteorMapPins>();
			}
			_harmony = new Harmony("com.srcodex.eternalmeteor");
			_harmony.PatchAll(typeof(EternalMeteorPlugin).Assembly);
			Log.Info("Config", string.Format("{0} {1} loaded, {2} game methods patched", "EternalMeteor", "1.2.3", _harmony.GetPatchedMethods().Count()) + (IsHeadless ? ", on a dedicated server: visuals off" : string.Empty));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class Log
	{
		internal const string Meteor = "Meteor";

		internal const string Impact = "Impact";

		internal const string Shield = "Shield";

		internal const string Rock = "Rock";

		internal const string Assets = "Assets";

		internal const string Effects = "Effects";

		internal const string Config = "Config";

		internal const string Command = "Command";

		internal const string Map = "Map";

		internal const string Strange = "Strange";

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

		private static ManualLogSource s_source;

		internal static bool Verbose
		{
			get
			{
				if (ConfigManager.VerboseLogging != null)
				{
					return ConfigManager.VerboseLogging.Value;
				}
				return false;
			}
		}

		internal static void Init(ManualLogSource source)
		{
			s_source = source;
		}

		internal static void Info(string tag, string message)
		{
			ManualLogSource obj = s_source;
			if (obj != null)
			{
				obj.LogInfo((object)("[" + tag + "] " + message));
			}
		}

		internal static void Warning(string tag, string message)
		{
			ManualLogSource obj = s_source;
			if (obj != null)
			{
				obj.LogWarning((object)("[" + tag + "] " + message));
			}
		}

		internal static void Error(string tag, string message)
		{
			ManualLogSource obj = s_source;
			if (obj != null)
			{
				obj.LogError((object)("[" + tag + "] " + message));
			}
		}

		internal static void Debug(string tag, string message)
		{
			if (Verbose)
			{
				ManualLogSource obj = s_source;
				if (obj != null)
				{
					obj.LogInfo((object)("[" + tag + "] " + message));
				}
			}
		}

		internal static void ErrorOnce(string tag, string site, Exception exception)
		{
			if (s_reportedFailures.Add(site))
			{
				ManualLogSource obj = s_source;
				if (obj != null)
				{
					obj.LogError((object)$"[{tag}] {site} failed (later failures here are not logged): {exception}");
				}
			}
		}
	}
}
namespace EternalMeteor.Protection
{
	internal sealed class DomeVisual : MonoBehaviour
	{
		private sealed class Shown
		{
			internal ShieldGenerator Key;

			internal Vector3 Centre;

			internal float Radius;

			internal float HitTime;

			internal float Until;
		}

		private const float FullColour = 1f;

		private const float NeverHit = -1000f;

		private static DomeVisual s_instance;

		private readonly List<Shown> _flashes = new List<Shown>();

		private readonly Dictionary<ProtectionStone, Shown> _permanent = new Dictionary<ProtectionStone, Shown>();

		private readonly Stack<ShieldGenerator> _freeKeys = new Stack<ShieldGenerator>();

		private GameObject _keyRoot;

		private ShieldDomeImageEffect _effect;

		private float _nextSearch;

		private bool _dirty = true;

		internal static void Flash(Vector3 centre, float radius, float seconds)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_instance != (Object)null)
			{
				s_instance.AddFlash(centre, radius, seconds);
			}
		}

		internal static void Refresh()
		{
			if ((Object)(object)s_instance != (Object)null)
			{
				s_instance._dirty = true;
			}
		}

		private void Awake()
		{
			s_instance = this;
			ConfigManager.AlwaysShowDome.SettingChanged += delegate
			{
				_dirty = true;
			};
			ConfigManager.ProtectionRadius.SettingChanged += delegate
			{
				_dirty = true;
			};
		}

		private void Update()
		{
			if (!FindEffect())
			{
				return;
			}
			float time = Time.time;
			for (int num = _flashes.Count - 1; num >= 0; num--)
			{
				if (time >= _flashes[num].Until)
				{
					Hide(_flashes[num]);
					_flashes.RemoveAt(num);
				}
			}
			if (_dirty)
			{
				_dirty = false;
				SyncPermanent();
			}
		}

		private void AddFlash(Vector3 centre, float radius, float seconds)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!FindEffect())
			{
				return;
			}
			float time = Time.time;
			foreach (Shown value in _permanent.Values)
			{
				Vector3 val = value.Centre - centre;
				if (((Vector3)(ref val)).sqrMagnitude < 1f)
				{
					value.HitTime = time;
					Show(value);
					return;
				}
			}
			Shown shown = new Shown
			{
				Key = TakeKey(),
				Centre = centre,
				Radius = radius,
				HitTime = time,
				Until = time + seconds
			};
			_flashes.Add(shown);
			Show(shown);
		}

		private void SyncPermanent()
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			bool value = ConfigManager.AlwaysShowDome.Value;
			List<ProtectionStone> list = new List<ProtectionStone>();
			foreach (KeyValuePair<ProtectionStone, Shown> item in _permanent)
			{
				if ((Object)(object)item.Key == (Object)null || !ProtectionStone.Active.Contains(item.Key) || (!value && !item.Key.DomeOn))
				{
					list.Add(item.Key);
				}
			}
			foreach (ProtectionStone item2 in list)
			{
				Hide(_permanent[item2]);
				_permanent.Remove(item2);
			}
			foreach (ProtectionStone item3 in ProtectionStone.Active)
			{
				if (!((Object)(object)item3 == (Object)null) && (value || item3.DomeOn))
				{
					if (!_permanent.TryGetValue(item3, out var value2))
					{
						value2 = new Shown
						{
							Key = TakeKey(),
							HitTime = (item3.DomeOn ? Time.time : (-1000f))
						};
						_permanent[item3] = value2;
					}
					value2.Centre = ((Component)item3).transform.position;
					value2.Radius = ConfigManager.ProtectionRadius.Value;
					Show(value2);
				}
			}
		}

		private void Show(Shown dome)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			_effect.SetShieldData(dome.Key, dome.Centre, dome.Radius, 1f, dome.HitTime);
		}

		private void Hide(Shown dome)
		{
			if ((Object)(object)_effect != (Object)null)
			{
				_effect.RemoveShield(dome.Key);
			}
			_freeKeys.Push(dome.Key);
		}

		private bool FindEffect()
		{
			if ((Object)(object)_effect != (Object)null)
			{
				return true;
			}
			if (_flashes.Count > 0 || _permanent.Count > 0)
			{
				foreach (Shown flash in _flashes)
				{
					_freeKeys.Push(flash.Key);
				}
				foreach (Shown value in _permanent.Values)
				{
					_freeKeys.Push(value.Key);
				}
				_flashes.Clear();
				_permanent.Clear();
				_dirty = true;
			}
			if ((Object)(object)GameCamera.instance == (Object)null || Time.time < _nextSearch)
			{
				return false;
			}
			_nextSearch = Time.time + 2f;
			_effect = Object.FindFirstObjectByType<ShieldDomeImageEffect>();
			if ((Object)(object)_effect == (Object)null)
			{
				Log.ErrorOnce("Shield", "DomeVisual", new InvalidOperationException("the game's shield dome effect was not found: domes stay invisible"));
			}
			return (Object)(object)_effect != (Object)null;
		}

		private ShieldGenerator TakeKey()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (_freeKeys.Count > 0)
			{
				return _freeKeys.Pop();
			}
			if ((Object)(object)_keyRoot == (Object)null)
			{
				_keyRoot = new GameObject("EternalMeteor_DomeKeys");
				_keyRoot.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_keyRoot);
			}
			GameObject val = new GameObject("DomeKey");
			val.transform.SetParent(_keyRoot.transform, false);
			return val.AddComponent<ShieldGenerator>();
		}
	}
	internal static class ProtectionPiece
	{
		internal const string CrystalName = "crystal";

		internal static readonly Color RuneColour = new Color(0.22f, 0.95f, 0.85f);

		private const string BasePrefab = "guard_stone";

		private const string DescriptionToken = "$piece_eternalmeteor_description";

		private const string CategoryName = "EternalMeteor";

		private const float CrystalHeight = 3.16f;

		private static CustomPiece s_piece;

		internal static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += CreatePiece;
			PieceManager.OnPiecesRegistered += ApplyRecipe;
			ConfigManager.StoneAmount.SettingChanged += delegate
			{
				ApplyRecipe();
			};
			ConfigManager.FineWoodAmount.SettingChanged += delegate
			{
				ApplyRecipe();
			};
			ConfigManager.CopperAmount.SettingChanged += delegate
			{
				ApplyRecipe();
			};
			ConfigManager.ProtectionRadius.SettingChanged += delegate
			{
				ApplyRadius();
			};
		}

		private static void CreatePiece()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreatePiece;
			PieceConfig val = new PieceConfig();
			val.Name = "$piece_eternalmeteor";
			val.Description = "$piece_eternalmeteor_description";
			val.PieceTable = PieceTables.Hammer;
			val.Category = "EternalMeteor";
			val.Usage = new string[2]
			{
				PieceUsages.Misc,
				PieceUsages.Defense
			};
			val.CraftingStation = CraftingStations.Workbench;
			PieceConfig val2 = val;
			foreach (KeyValuePair<string, int> item in Requirements())
			{
				val2.AddRequirement(new RequirementConfig(item.Key, item.Value, 0, true));
			}
			if (!EternalMeteorPlugin.IsHeadless)
			{
				Sprite val3 = AssetLoader.Sprite("Icons/eternalmeteor_stone.png");
				if ((Object)(object)val3 != (Object)null)
				{
					val2.Icon = val3;
				}
			}
			s_piece = new CustomPiece("piece_eternalmeteor", "guard_stone", val2);
			if ((Object)(object)s_piece.PiecePrefab == (Object)null)
			{
				Log.Error("Shield", "guard_stone not found: the EternalMeteor stone cannot be built");
				return;
			}
			Customize(s_piece.PiecePrefab);
			PieceManager.Instance.AddPiece(s_piece);
		}

		private static void Customize(GameObject prefab)
		{
			PrivateArea component = prefab.GetComponent<PrivateArea>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Transform val = prefab.transform.Find("PlayerBase");
			if ((Object)(object)val != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
			}
			Transform val2 = prefab.transform.Find("InRangeIndicator");
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			Transform val3 = prefab.transform.Find("WayEffect");
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(true);
				TintGlow(((Component)val3).gameObject);
			}
			CircleProjector componentInChildren = prefab.GetComponentInChildren<CircleProjector>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.m_radius = ConfigManager.ProtectionRadius.Value;
				componentInChildren.m_nrOfSegments = 100;
				((Component)componentInChildren).gameObject.SetActive(true);
			}
			ReplaceModel(prefab);
			prefab.AddComponent<ProtectionStone>();
		}

		private static void TintGlow(GameObject glow)
		{
			//IL_000f: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Light[] componentsInChildren = glow.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].color = RuneColour;
			}
			ParticleSystem[] componentsInChildren2 = glow.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				MainModule main = componentsInChildren2[i].main;
				((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(RuneColour.r, RuneColour.g, RuneColour.b, 0.8f));
			}
		}

		private static void ReplaceModel(GameObject prefab)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			Transform val = prefab.transform.Find("new/default");
			Mesh val2 = AssetLoader.Mesh("Stone/monolith.obj");
			Mesh val3 = AssetLoader.Mesh("Stone/crystal.obj");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Log.Warning("Shield", "monolith model missing: the EternalMeteor stone keeps the guard stone's look");
				return;
			}
			val.localPosition = Vector3.zero;
			val.localRotation = Quaternion.identity;
			val.localScale = Vector3.one;
			((Component)val).GetComponent<MeshFilter>().sharedMesh = val2;
			MeshCollider component = ((Component)val).GetComponent<MeshCollider>();
			if ((Object)(object)component != (Object)null)
			{
				component.sharedMesh = val2;
			}
			MeshRenderer component2 = ((Component)val).GetComponent<MeshRenderer>();
			Material val4 = Find(((Renderer)component2).sharedMaterials, "Custom/Piece") ?? ((Renderer)component2).sharedMaterials[0];
			Material original = Find(((Renderer)component2).sharedMaterials, "Standard") ?? val4;
			if (!EternalMeteorPlugin.IsHeadless)
			{
				((Renderer)component2).sharedMaterials = (Material[])(object)new Material[1] { StoneMaterial(val4) };
			}
			if (!((Object)(object)val3 == (Object)null))
			{
				GameObject val5 = new GameObject("crystal");
				val5.transform.SetParent(prefab.transform, false);
				val5.transform.localPosition = Vector3.up * 3.16f;
				val5.AddComponent<MeshFilter>().sharedMesh = val3;
				MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
				((Renderer)val6).shadowCastingMode = (ShadowCastingMode)0;
				if (!EternalMeteorPlugin.IsHeadless)
				{
					((Renderer)val6).sharedMaterial = CrystalMaterial(original);
				}
				GameObject val7 = new GameObject("CrystalLight");
				val7.transform.SetParent(val5.transform, false);
				Light obj = val7.AddComponent<Light>();
				obj.type = (LightType)2;
				obj.color = RuneColour;
				obj.range = 7f;
				obj.intensity = 1.4f;
				obj.shadows = (LightShadows)0;
			}
		}

		private static Material StoneMaterial(Material original)
		{
			//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_0012: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(original)
			{
				name = "EternalMeteor_Monolith"
			};
			Texture2D texture = AssetLoader.Texture("Stone/monolith_albedo.png", linear: false, normalMap: false, (FilterMode)0);
			Texture2D texture2 = AssetLoader.Texture("Stone/monolith_normal.png", linear: true, normalMap: true, (FilterMode)1);
			Texture2D val2 = AssetLoader.Texture("Stone/monolith_emission.png", linear: false, normalMap: false, (FilterMode)0);
			SetTexture(val, "_MainTex", texture);
			SetTexture(val, "_BumpMap", texture2);
			if ((Object)(object)val2 != (Object)null && val.HasProperty("_EmissionColor"))
			{
				SetTexture(val, "_EmissionMap", val2);
				val.EnableKeyword("_EMISSION");
				val.SetColor("_EmissionColor", RuneColour * 2.2f);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			Log.Info("Shield", "monolith material from " + ((Object)original).name + " (" + ((Object)original.shader).name + ")");
			return val;
		}

		private static Material CrystalMaterial(Material original)
		{
			//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_0012: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(original)
			{
				name = "EternalMeteor_Crystal"
			};
			Texture2D val2 = AssetLoader.Texture("Stone/crystal_albedo.png", linear: false, normalMap: false, (FilterMode)0);
			SetTexture(val, "_MainTex", val2);
			if (val.HasProperty("_BumpMap"))
			{
				val.SetTexture("_BumpMap", (Texture)null);
				val.DisableKeyword("_NORMALMAP");
			}
			if (val.HasProperty("_EmissionMap"))
			{
				val.SetTexture("_EmissionMap", (Texture)(object)val2);
			}
			if (val.HasProperty("_EmissionColor"))
			{
				val.EnableKeyword("_EMISSION");
				val.SetColor("_EmissionColor", RuneColour * 2.6f);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", 0.85f);
			}
			return val;
		}

		private static void SetTexture(Material material, string property, Texture2D texture)
		{
			if ((Object)(object)texture != (Object)null && material.HasProperty(property))
			{
				material.SetTexture(property, (Texture)(object)texture);
			}
		}

		private static Material Find(Material[] materials, string shader)
		{
			foreach (Material val in materials)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.shader != (Object)null && ((Object)val.shader).name == shader)
				{
					return val;
				}
			}
			return null;
		}

		private static IEnumerable<KeyValuePair<string, int>> Requirements()
		{
			if (ConfigManager.StoneAmount.Value > 0)
			{
				yield return new KeyValuePair<string, int>("Stone", ConfigManager.StoneAmount.Value);
			}
			if (ConfigManager.FineWoodAmount.Value > 0)
			{
				yield return new KeyValuePair<string, int>("FineWood", ConfigManager.FineWoodAmount.Value);
			}
			if (ConfigManager.CopperAmount.Value > 0)
			{
				yield return new KeyValuePair<string, int>("Copper", ConfigManager.CopperAmount.Value);
			}
		}

		private static void ApplyRecipe()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00b8: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			CustomPiece obj = s_piece;
			Piece val = ((obj != null) ? obj.Piece : null);
			if ((Object)(object)val == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			List<Requirement> list = new List<Requirement>();
			foreach (KeyValuePair<string, int> item in Requirements())
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key);
				ItemDrop val2 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Log.Warning("Shield", "recipe item " + item.Key + " not found");
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val2,
					m_amount = item.Value,
					m_recover = true
				});
			}
			val.m_resources = list.ToArray();
			PieceTable pieceTable = PieceManager.Instance.GetPieceTable(PieceTables.Hammer);
			bool num = (Object)(object)pieceTable != (Object)null && pieceTable.m_pieces.Contains(s_piece.PiecePrefab);
			string arg = string.Join(", ", list.ConvertAll((Requirement r) => $"{r.m_amount} {((Object)r.m_resItem).name}"));
			if (num)
			{
				Log.Info("Shield", string.Format("stone in the hammer menu: tab {0}, tags {1}; recipe {2}", "EternalMeteor", val.m_usage, arg));
			}
			else
			{
				Log.Error("Shield", "the stone is not in the hammer's piece table: it cannot be built");
			}
		}

		private static void ApplyRadius()
		{
			CustomPiece obj = s_piece;
			CircleProjector val = (((Object)(object)((obj != null) ? obj.PiecePrefab : null) != (Object)null) ? s_piece.PiecePrefab.GetComponentInChildren<CircleProjector>(true) : null);
			if ((Object)(object)val != (Object)null)
			{
				val.m_radius = ConfigManager.ProtectionRadius.Value;
			}
			DomeVisual.Refresh();
		}
	}
	internal sealed class ProtectionStone : MonoBehaviour, Hoverable, Interactable
	{
		internal const string PrefabName = "piece_eternalmeteor";

		internal const string NameToken = "$piece_eternalmeteor";

		internal static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("piece_eternalmeteor");

		internal static readonly List<ProtectionStone> Active = new List<ProtectionStone>();

		private const float SpinDegreesPerSecond = 40f;

		private const float BobHeight = 0.12f;

		private const string ToggleRpc = "EternalMeteor_ToggleDome";

		private static readonly int DomeKey = StringExtensionMethods.GetStableHashCode("eternalmeteor_dome");

		private ZNetView _nview;

		private CircleProjector _marker;

		private Transform _crystal;

		private Vector3 _crystalRest;

		private bool _domeSeen;

		internal Dome Dome => new Dome(((Component)this).transform.position.ToVec3(), ConfigManager.ProtectionRadius.Value);

		internal bool DomeOn
		{
			get
			{
				if ((Object)(object)_nview != (Object)null && _nview.IsValid())
				{
					return _nview.GetZDO().GetBool(DomeKey, false);
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			_nview = ((Component)this).GetComponent<ZNetView>();
			_marker = ((Component)this).GetComponentInChildren<CircleProjector>(true);
			_crystal = ((Component)this).transform.Find("crystal");
			if ((Object)(object)_crystal != (Object)null)
			{
				_crystalRest = _crystal.localPosition;
			}
			if ((Object)(object)_marker != (Object)null)
			{
				_marker.m_radius = ConfigManager.ProtectionRadius.Value;
			}
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				if ((Object)(object)_marker != (Object)null)
				{
					((Component)_marker).gameObject.SetActive(false);
				}
				_nview.Register("EternalMeteor_ToggleDome", (Action<long>)RPC_ToggleDome);
				_domeSeen = DomeOn;
				((MonoBehaviour)this).InvokeRepeating("WatchDome", 0.5f, 0.5f);
				Active.Add(this);
				DomeVisual.Refresh();
			}
		}

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

		private void Update()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_crystal == (Object)null))
			{
				float num = Time.time + ((Component)this).transform.position.x;
				_crystal.localRotation = Quaternion.Euler(0f, num * 40f % 360f, 0f);
				_crystal.localPosition = _crystalRest + Vector3.up * (0.12f * Mathf.Sin(num * 1.3f));
			}
		}

		public string GetHoverText()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return string.Empty;
			}
			ShowMarker();
			string text = ConfigManager.ProtectionRadius.Value.ToString("0");
			string text2 = (DomeOn ? "$piece_eternalmeteor_hide" : "$piece_eternalmeteor_show");
			return Localization.instance.Localize("$piece_eternalmeteor\n<color=#5FE8D8>$piece_eternalmeteor_hover</color>\n[<color=yellow><b>$KEY_Use</b></color>] " + text2, new string[1] { text });
		}

		public string GetHoverName()
		{
			return "$piece_eternalmeteor";
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || (Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			_nview.InvokeRPC("EternalMeteor_ToggleDome", Array.Empty<object>());
			return true;
		}

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

		private void RPC_ToggleDome(long sender)
		{
			if (_nview.IsOwner())
			{
				_nview.GetZDO().Set(DomeKey, !DomeOn);
			}
		}

		private void WatchDome()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			bool domeOn = DomeOn;
			if (domeOn != _domeSeen)
			{
				_domeSeen = domeOn;
				DomeVisual.Refresh();
				if (domeOn && !EternalMeteorPlugin.IsHeadless)
				{
					MeteorEffects.PlayAt("Sounds/dome_hum.wav", ((Component)this).transform.position + Vector3.up * 3f, 0.8f, 20f, 150f, 0f);
				}
			}
		}

		private void ShowMarker()
		{
			if (!((Object)(object)_marker == (Object)null))
			{
				_marker.m_radius = ConfigManager.ProtectionRadius.Value;
				((Component)_marker).gameObject.SetActive(true);
				((MonoBehaviour)this).CancelInvoke("HideMarker");
				((MonoBehaviour)this).Invoke("HideMarker", 0.5f);
			}
		}

		private void HideMarker()
		{
			if ((Object)(object)_marker != (Object)null)
			{
				((Component)_marker).gameObject.SetActive(false);
			}
		}
	}
}
namespace EternalMeteor.Patches
{
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class GameStartPatch
	{
		private static void Postfix()
		{
			MeteorNetwork.Register();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")]
	internal static class ObjectDBUpdateRegistersPatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			MeteorPrefabs.AddTerrainOps(__instance);
		}
	}
	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	internal static class AttackOnAttackTriggerPatch
	{
		private static void Prefix(Attack __instance, out int __state)
		{
			__state = FreeShots.AmmoBefore(__instance);
		}

		private static void Postfix(Attack __instance, int __state)
		{
			FreeShots.AfterShot(__instance, __state);
		}
	}
	[HarmonyPatch(typeof(Player), "QueueReloadAction")]
	internal static class PlayerQueueReloadActionPatch
	{
		private static void Postfix(Player __instance)
		{
			FreeShots.Reloading(__instance);
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	internal static class CharacterDropGenerateDropListPatch
	{
		private static void Postfix(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result)
		{
			HunterDrops.AddTo(__instance, __result);
		}
	}
}
namespace EternalMeteor.Meteor
{
	internal sealed class LightFade : MonoBehaviour
	{
		internal float Seconds = 2f;

		private Light _light;

		private float _start;

		private float _intensity;

		private void Start()
		{
			_light = ((Component)this).GetComponent<Light>();
			_start = Time.time;
			_intensity = _light.intensity;
		}

		private void Update()
		{
			float num = (Time.time - _start) / Mathf.Max(0.05f, Seconds);
			if (num >= 1f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else
			{
				_light.intensity = _intensity * (1f - num) * (1f - num);
			}
		}
	}
	internal sealed class Debris : MonoBehaviour
	{
		private const float Gravity = 22f;

		private const float MaxSeconds = 7f;

		internal Vector3 Velocity;

		internal Vector3 Spin;

		internal bool Explodes;

		private float _age;

		private void Update()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			_age += deltaTime;
			Velocity += Vector3.down * (22f * deltaTime);
			Transform transform = ((Component)this).transform;
			transform.position += Velocity * deltaTime;
			((Component)this).transform.Rotate(Spin * deltaTime, (Space)1);
			bool flag = Velocity.y < 0f && ((Component)this).transform.position.y <= MeteorEffects.GroundOr(((Component)this).transform.position, float.MinValue) + 0.3f;
			if (flag || !(_age < 7f))
			{
				if (flag && Explodes)
				{
					MeteorEffects.Spawn("fx_siegebomb_explosion", ((Component)this).transform.position, Quaternion.identity, 0.6f, 8f);
				}
				MeteorEffects.Extinguish(((Component)this).gameObject);
				Object.Destroy((Object)(object)this);
			}
		}
	}
	internal sealed class ScreenFlash : MonoBehaviour
	{
		private const float Seconds = 1.6f;

		private static ScreenFlash s_instance;

		private Image _image;

		private float _strength;

		private float _start = -10f;

		internal static void Show(float strength)
		{
			strength = Mathf.Clamp01(strength);
			if (!(strength <= 0.02f))
			{
				if ((Object)(object)s_instance == (Object)null)
				{
					s_instance = Create();
				}
				float num = s_instance.Current();
				if (!(strength < num))
				{
					s_instance._strength = strength;
					s_instance._start = Time.time;
					((Behaviour)s_instance).enabled = true;
				}
			}
		}

		private static ScreenFlash Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002d: 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_0066: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("EternalMeteor_ScreenFlash");
			Object.DontDestroyOnLoad((Object)(object)val);
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32000;
			GameObject val2 = new GameObject("Flash");
			val2.transform.SetParent(val.transform, false);
			Image val3 = val2.AddComponent<Image>();
			((Graphic)val3).raycastTarget = false;
			((Graphic)val3).color = new Color(1f, 0.97f, 0.9f, 0f);
			RectTransform rectTransform = ((Graphic)val3).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = Vector2.zero;
			rectTransform.offsetMax = Vector2.zero;
			ScreenFlash screenFlash = val.AddComponent<ScreenFlash>();
			screenFlash._image = val3;
			return screenFlash;
		}

		private float Current()
		{
			float num = (Time.time - _start) / 1.6f;
			if (!(num >= 1f))
			{
				return _strength * (1f - num) * (1f - num);
			}
			return 0f;
		}

		private void Update()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			float num = Current();
			Color color = ((Graphic)_image).color;
			color.a = 0.92f * num;
			((Graphic)_image).color = color;
			if (num <= 0f)
			{
				((Behaviour)this).enabled = false;
			}
		}
	}
	internal sealed class MeteorCrater : MonoBehaviour
	{
		internal const string PrefabName = "EternalMeteor_Crater";

		internal static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("EternalMeteor_Crater");

		internal static readonly int LootKey = StringExtensionMethods.GetStableHashCode("eternalmeteor_loot");

		internal static readonly int BornKey = StringExtensionMethods.GetStableHashCode("eternalmeteor_born");

		private static readonly int StageKey = StringExtensionMethods.GetStableHashCode("eternalmeteor_stage");

		private const float RockDelay = 1.5f;

		private const float FireSafetySeconds = 15f;

		private const int StageNew = 0;

		private const int StageDug = 1;

		private const int StageRock = 2;

		private readonly List<GameObject> _fires = new List<GameObject>();

		private ZNetView _nview;

		private float _dugAt = -1f;

		private static float BurnSeconds => ConfigManager.CraterBurnSeconds.Value;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Start()
		{
			if ((Object)(object)_nview != (Object)null && _nview.IsValid())
			{
				((MonoBehaviour)this).InvokeRepeating("Tick", 0.25f, 0.5f);
			}
		}

		private void Tick()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!_nview.IsValid() || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			try
			{
				ZDO zDO = _nview.GetZDO();
				double age = ZNet.instance.GetTimeSeconds() - (double)zDO.GetLong(BornKey, 0L) / 1000.0;
				UpdateFires(age, zDO.GetInt(StageKey, 0));
				if (_nview.IsOwner() && ZoneSystem.instance.IsZoneLoaded(((Component)this).transform.position))
				{
					Advance(zDO, age);
				}
			}
			catch (Exception exception)
			{
				Log.ErrorOnce("Rock", "MeteorCrater.Tick", exception);
			}
		}

		private void Advance(ZDO zdo, double age)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			switch (zdo.GetInt(StageKey, 0))
			{
			case 0:
				MeteorPrefabs.DigCrater(Ground(((Component)this).transform.position));
				zdo.Set(StageKey, 1, false);
				_dugAt = Time.time;
				break;
			case 1:
				if (!(_dugAt > 0f) || !(Time.time - _dugAt < 1.5f))
				{
					RaiseMeteorite(zdo);
					zdo.Set(StageKey, 2, false);
				}
				break;
			default:
				if (age > (double)BurnSeconds)
				{
					ZNetScene.instance.Destroy(((Component)this).gameObject);
				}
				break;
			}
		}

		private void RaiseMeteorite(ZDO zdo)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab(MeteoriteRock.PrefabHash);
			if ((Object)(object)prefab == (Object)null)
			{
				Log.Error("Rock", "the meteorite prefab is not registered: no rock for this crater");
				return;
			}
			Vector3 val = Ground(((Component)this).transform.position) + Vector3.down * 1.8f;
			Quaternion val2 = Quaternion.Euler(Random.Range(-8f, 8f), Random.Range(0f, 360f), Random.Range(-8f, 8f));
			Object.Instantiate<GameObject>(prefab, val, val2).GetComponent<MeteoriteRock>().Init(zdo.GetString(LootKey, ""), zdo.GetLong(BornKey, 0L));
			Log.Info("Rock", string.Format("meteorite raised at ({0:0}, {1:0}, {2:0}): {3}", val.x, val.y, val.z, zdo.GetString(LootKey, "")));
		}

		private void UpdateFires(double age, int stage)
		{
			bool flag = age < (double)BurnSeconds && stage == 2 && !EternalMeteorPlugin.IsHeadless;
			if (flag && _fires.Count == 0)
			{
				LightFires((float)((double)BurnSeconds - age));
			}
			else
			{
				if (flag || _fires.Count <= 0)
				{
					return;
				}
				foreach (GameObject fire in _fires)
				{
					MeteorEffects.Extinguish(fire);
				}
				_fires.Clear();
			}
		}

		private void LightFires(float seconds)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(4f, ConfigManager.CraterRadius.Value);
			Random random = new Random(((object)Unsafe.As<ZDOID, ZDOID>(ref _nview.GetZDO().m_uid)/*cast due to .constrained prefix*/).GetHashCode());
			for (int i = 0; i < 7; i++)
			{
				double num2 = ((double)i + random.NextDouble() * 0.6) / 7.0 * 3.1415927410125732 * 2.0;
				float num3 = num * (0.35f + 0.55f * (float)random.NextDouble());
				Vector3 point = ((Component)this).transform.position + new Vector3((float)Math.Sin(num2), 0f, (float)Math.Cos(num2)) * num3;
				AddFire(MeteorEffects.Spawn("fx_BonfireFlames", Ground(point), Quaternion.identity, 1f + (float)random.NextDouble() * 0.8f, seconds + 15f));
			}
			AddFire(MeteorEffects.Spawn("fx_BonfireFlames", Ground(((Component)this).transform.position) + Vector3.up * 2f, Quaternion.identity, 3f, seconds + 15f));
			GameObject val = new GameObject("EternalMeteor_CraterGlow");
			val.transform.SetParent(((Component)this).transform, false);
			val.transform.position = Ground(((Component)this).transform.position) + Vector3.up * 3f;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = MeteorEffects.Ember;
			obj.range = num * 3f;
			obj.intensity = 2.2f;
			obj.shadows = (LightShadows)0;
			_fires.Add(val);
		}

		private void AddFire(GameObject fire)
		{
			if ((Object)(object)fire != (Object)null)
			{
				fire.transform.SetParent(((Component)this).transform, true);
				_fires.Add(fire);
			}
		}

		private static Vector3 Ground(Vector3 point)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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)
			point.y = MeteorEffects.GroundOr(point, point.y);
			return point;
		}
	}
	internal sealed class MeteorDirector : MonoBehaviour
	{
		private const float StartDistance = 1100f;

		private const double LeadSeconds = 0.6;

		private const float BounceSeconds = 2.6f;

		private const float DomeSearchRange = 400f;

		private const float DungeonHeight = 1000f;

		private const int TargetAttempts = 12;

		private readonly Random _rng = new Random();

		private readonly OreCadence _strangeOre = new OreCadence();

		private readonly List<MeteorEvent> _falling = new List<MeteorEvent>();

		private double _nextRandom = -1.0;

		private int _nextId = 1;

		internal static MeteorDirector Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			ConfigManager.MinIntervalMinutes.SettingChanged += delegate
			{
				_nextRandom = -1.0;
			};
			ConfigManager.MaxIntervalMinutes.SettingChanged += delegate
			{
				_nextRandom = -1.0;
			};
			ConfigManager.RandomMeteors.SettingChanged += delegate
			{
				_nextRandom = -1.0;
			};
			ConfigManager.MapPins.SettingChanged += delegate
			{
				MeteorSites.Resend();
			};
		}

		private void Update()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null || WorldGenerator.instance == null || (Object)(object)ZNetScene.instance == (Object)null || ZRoutedRpc.instance == null)
			{
				_nextRandom = -1.0;
				_falling.Clear();
				MeteorSites.Reset();
				return;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			try
			{
				UpdateRandomMeteors(timeSeconds);
				UpdateLandings(timeSeconds);
				MeteorSites.Update(timeSeconds);
			}
			catch (Exception exception)
			{
				Log.ErrorOnce("Meteor", "MeteorDirector.Update", exception);
			}
		}

		internal void Launch(Vector3 target, long anchor, string reason, bool ignoreProgression = false)
		{
			//IL_001a: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				List<Dome> list = WorldScan.FindDomes(target, 400f);
				float num = ConfigManager.CraterRadius.Value + 2f;
				target = Domes.KeepClear(list, target.ToVec3(), num).ToVector3();
				target.y = GroundHeight(target);
				float azimuthDegrees = (float)(_rng.NextDouble() * 360.0);
				float inclineDegrees = 38f + (float)(_rng.NextDouble() * 20.0);
				float bounceMargin = Mathf.Max(ConfigManager.BounceMargin.Value, num);
				Trajectory trajectory = Trajectory.Plan(target.ToVec3(), azimuthDegrees, inclineDegrees, 1100f, ConfigManager.FallSeconds.Value, list, bounceMargin, 2.6f);
				Vector3 val = trajectory.Landing.ToVector3();
				if (trajectory.Deflected)
				{
					val.y = GroundHeight(val);
				}
				MeteorEvent meteorEvent = new MeteorEvent
				{
					Id = _nextId++,
					LaunchTime = ZNet.instance.GetTimeSeconds() + 0.6,
					Start = trajectory.Start.ToVector3(),
					Target = target,
					Burst = (trajectory.Deflected ? trajectory.Burst.ToVector3() : val),
					Landing = val,
					FallSeconds = trajectory.FallSeconds,
					BurstSeconds = trajectory.BurstSeconds,
					LandingSeconds = trajectory.LandingSeconds,
					Deflected = trajectory.Deflected,
					Radius = ConfigManager.ImpactRadius.Value,
					Anchor = anchor,
					Loot = RollLoot(ignoreProgression),
					Seed = _rng.Next()
				};
				if (trajectory.Deflected)
				{
					meteorEvent.DomeCentre = list[trajectory.DomeIndex].Centre.ToVector3();
					meteorEvent.DomeRadius = list[trajectory.DomeIndex].Radius;
				}
				meteorEvent.Domes.AddRange(list);
				MeteorNetwork.Broadcast(meteorEvent);
				_falling.Add(meteorEvent);
				Log.Info("Meteor", $"meteor {meteorEvent.Id} ({reason}) falls on {Describe(target)} in {meteorEvent.FallSeconds:0} s" + (trajectory.Deflected ? (", bounced by a dome to " + Describe(val)) : string.Empty) + "; meteorite: " + meteorEvent.Loot);
			}
		}

		private void UpdateRandomMeteors(double now)
		{
			if (!ConfigManager.RandomMeteors.Value)
			{
				_nextRandom = -1.0;
			}
			else if (_nextRandom < 0.0)
			{
				ScheduleNext(now);
			}
			else if (!(now < _nextRandom))
			{
				ScheduleNext(now);
				LaunchRandom();
			}
		}

		private void ScheduleNext(double now)
		{
			double num = Targeting.NextDelay(_rng, (double)ConfigManager.MinIntervalMinutes.Value * 60.0, (double)ConfigManager.MaxIntervalMinutes.Value * 60.0);
			_nextRandom = now + num;
			Log.Info("Meteor", $"next random meteor in {num / 60.0:0.0} min");
		}

		private void LaunchRandom()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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)
			List<KeyValuePair<long, Vector3>> list = PlayersOnTheSurface();
			if (list.Count == 0)
			{
				Log.Debug("Meteor", "no player on the surface: this meteor was skipped");
				return;
			}
			KeyValuePair<long, Vector3> keyValuePair = list[_rng.Next(list.Count)];
			for (int i = 0; i < 12; i++)
			{
				Vector3 val = Targeting.PointAround(_rng, keyValuePair.Value.ToVec3(), ConfigManager.MinDistance.Value, ConfigManager.MaxDistance.Value).ToVector3();
				float num = GroundHeight(val);
				if (ConfigManager.AllowOcean.Value || !(num < ZoneSystem.instance.m_waterLevel + 1f))
				{
					val.y = num;
					Launch(val, keyValuePair.Key, "random");
					return;
				}
			}
			Log.Info("Meteor", "no dry land found around " + Describe(keyValuePair.Value) + ": this meteor was skipped");
		}

		private void UpdateLandings(double now)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			for (int num = _falling.Count - 1; num >= 0; num--)
			{
				MeteorEvent meteorEvent = _falling[num];
				if (!(now < meteorEvent.LandingTime))
				{
					_falling.RemoveAt(num);
					List<Dome> domes = WorldScan.FindDomes(meteorEvent.Landing, meteorEvent.Radius + ConfigManager.ProtectionRadius.Value + 1f);
					WorldScan.DestroyUnloaded(meteorEvent, domes);
					WorldScan.CreateCrater(meteorEvent);
					MeteorSites.Landed(meteorEvent.Landing);
				}
			}
		}

		private string RollLoot(bool ignoreProgression)
		{
			bool progression = ConfigManager.FollowProgression.Value;
			List<LootMaterial> list = MeteorLoot.Unlocked(ConfigManager.ParsedMaterials(), (string key) => !progression || ZoneSystem.instance.GetGlobalKey(key));
			list.RemoveAll(delegate(LootMaterial material)
			{
				int num;
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					num = (((Object)(object)ObjectDB.instance.GetItemPrefab(material.Prefab) == (Object)null) ? 1 : 0);
					if (num != 0)
					{
						Log.Warning("Config", "material " + material.Prefab + " is not an item of this game: left out of meteorites");
					}
				}
				else
				{
					num = 0;
				}
				return (byte)num != 0;
			});
			List<LootEntry> list2 = MeteorLoot.Roll(_rng, list, ConfigManager.MaterialChance.Value);
			LootMaterial lootMaterial = StrangeItems.OreMaterial(ignoreProgression);
			if (lootMaterial != null)
			{
				bool flag = _strangeOre.Next(_rng, ConfigManager.StrangeOreChance.Value);
				MeteorLoot.RollOnce(list2, _rng, lootMaterial, flag ? 1f : 0f);
			}
			return MeteorLoot.Serialize(list2);
		}

		private static List<KeyValuePair<long, Vector3>> PlayersOnTheSurface()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<long, Vector3>> list = new List<KeyValuePair<long, Vector3>>();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer.IsReady() && peer.m_characterID != ZDOID.None && peer.m_refPos.y < 1000f)
				{
					list.Add(new KeyValuePair<long, Vector3>(peer.m_uid, peer.m_refPos));
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if (!ZNet.instance.IsDedicated() && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && ((Component)localPlayer).transform.position.y < 1000f)
			{
				list.Add(new KeyValuePair<long, Vector3>(ZNet.GetUID(), ((Component)localPlayer).transform.position));
			}
			return list;
		}

		private static float GroundHeight(Vector3 point)
		{
			//IL_0005: 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_0029: 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)
			float result = default(float);
			if (ZoneSystem.instance.IsZoneLoaded(point) && ZoneSystem.instance.GetGroundHeight(point, ref result))
			{
				return result;
			}
			return WorldGenerator.instance.GetHeight(point.x, point.z);
		}

		private static string Describe(Vector3 point)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			return $"({point.x:0}, {point.y:0}, {point.z:0})";
		}
	}
	internal static class MeteorEffects
	{
		private const float SoundSpeed = 343f;

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

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

		private static GameObject s_templates;

		private static GameObject s_ringSegment;

		private static Material[] s_ringMaterials;

		private static Material s_meteorMaterial;

		private static bool s_meteorMaterialTried;

		private static AudioMixerGroup s_sfxGroup;

		private static bool s_sfxGroupSearched;

		internal static Color Ember => new Color(1f, 0.55f, 0.22f);

		internal static Vector3 Listener()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GameCamera.instance != (Object)null)
			{
				return ((Component)GameCamera.instance).transform.position;
			}
			if (!((Object)(object)Player.m_localPlayer != (Object)null))
			{
				return Vector3.zero;
			}
			return ((Component)Player.m_localPlayer).transform.position;
		}

		internal static GameObject Spawn(string prefabName, Vector3 position, Quaternion rotation, float scale, float lifetime)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Prefab(prefabName);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ZNetView.m_forceDisableInit = true;
			GameObject val2;
			try
			{
				val2 = Object.Instantiate<GameObject>(val, position, rotation);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
			if (!ConfigManager.CameraShake.Value)
			{
				CamShaker[] componentsInChildren = val2.GetComponentsInChildren<CamShaker>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
			}
			ShieldDomeParticleColor[] componentsInChildren2 = val2.GetComponentsInChildren<ShieldDomeParticleColor>(true);
			foreach (ShieldDomeParticleColor val3 in componentsInChildren2)
			{
				Color val4 = DomeColour();
				ParticleSystem[] array = (ParticleSystem[])(((object)val3.m_particleSyste