Decompiled source of Valquake v0.1.5

Valquake.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Valquake")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Valquake")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace neobotics.ValheimMods;

public class AudioHelper : MonoBehaviour
{
	private Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();

	public void Awake()
	{
		Logging.GetLogger().Debug("AudioHelper.Awake");
		LoadAudioResources();
		ZRoutedRpc.instance.Register<Vector3, string>("NeoPlayClip", (Action<long, Vector3, string>)RPC_NeoPlayClip);
	}

	public void RPC_NeoPlayClip(long sender, Vector3 sourcePoint, string clipName)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		Logging.GetLogger().Debug("AudioHelper.RPC_NeoPlayClip");
		if (ZNet.instance.IsDedicated())
		{
			return;
		}
		try
		{
			NeoPlayClip(sourcePoint, clipName);
		}
		catch (Exception e)
		{
			Logging.GetLogger().Error(e, stackTrace: false);
		}
	}

	public void Play(Vector3 sourcePoint, string clipName)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		Logging.GetLogger().Debug("AudioHelper.Play");
		ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NeoPlayClip", new object[2] { sourcePoint, clipName });
	}

	public void NeoPlayClip(Vector3 sourcePoint, string clipName)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: 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)
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		NeoPlayClip(sourcePoint, position, clipName);
	}

	public void NeoPlayClip(Vector3 sourcePoint, Vector3 targetPoint, string clipName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		Logging.GetLogger().Debug("AudioHelper.NeoPlayClip");
		Vector3 val = sourcePoint - targetPoint;
		Vector3 normalized = ((Vector3)(ref val)).normalized;
		float num = (Vector3.Distance(sourcePoint, targetPoint) + 1f) / 10f;
		if (audioClips.TryGetValue(clipName.ToLower(), out var value))
		{
			AudioSource.PlayClipAtPoint(value, targetPoint + normalized * num, 1f);
		}
		else
		{
			Logging.GetLogger().Warning("Couldn't find audio clip for " + clipName);
		}
	}

	public float GetClipDuration(string clipName)
	{
		if (!audioClips.TryGetValue(clipName.ToLower(), out var value))
		{
			return -1f;
		}
		return value.length;
	}

	private void LoadAudioResources()
	{
		Logging.GetLogger().Debug("AudioHelper.LoadAudioResources");
		FileInfo fileInfo = new FileInfo(Assembly.GetExecutingAssembly().Location);
		string[] array = new string[0];
		List<string> obj = new List<string> { "*.wav", "*.mp3", "*.wma" };
		string directoryName = fileInfo.DirectoryName;
		Logging.GetLogger().Debug("filePath " + directoryName);
		audioClips.Clear();
		foreach (string item in obj)
		{
			array = CollectionExtensions.AddRangeToArray<string>(array, Directory.GetFiles(directoryName, item, SearchOption.TopDirectoryOnly));
		}
		Logging.GetLogger().Info($"Found {array.Length} audio files");
		((MonoBehaviour)this).StartCoroutine(Co_LoadAudio(directoryName, array));
	}

	private IEnumerator Co_LoadAudio(string filePath, string[] audioFiles)
	{
		WWW URL = null;
		for (int f = 0; f < audioFiles.Length; f++)
		{
			string clipUri = new Uri(audioFiles[f]).AbsoluteUri;
			string clipName = audioFiles[f].Substring(filePath.Length + 1);
			Logging.GetLogger().Debug("Loading audio clip " + clipName);
			try
			{
				URL = new WWW(clipUri);
			}
			catch (Exception ex)
			{
				Logging.GetLogger().Warning("Can't find audio resource: " + ex.Message);
			}
			yield return URL;
			if (URL != null)
			{
				try
				{
					AudioClip audioClip = URL.GetAudioClip(true, false);
					audioClips.Add(clipName.ToLower(), audioClip);
				}
				catch (Exception ex2)
				{
					Logging.GetLogger().Warning("Failed to load clip " + clipUri + ": " + ex2.Message);
				}
			}
			else
			{
				Logging.GetLogger().Warning("Failed to get URL for " + clipUri);
			}
		}
	}
}
public class CrossPlatformRandom : Random
{
	private const int LCG_MULTIPLIER = 134775813;

	private const int LCG_INCREMENT = 1;

	private int _seed;

	public float value => (float)NextDouble();

	public CrossPlatformRandom()
	{
		Random random = new Random();
		_seed = random.Next();
	}

	public CrossPlatformRandom(int seed)
	{
		_seed = seed;
	}

	public float Range(int min, int max)
	{
		return Next(min, max);
	}

	public float Range(float min, float max)
	{
		return Mathf.Lerp(min, max, (float)NextDouble());
	}

	private int GetNext()
	{
		_seed = _seed * 134775813 + 1;
		return _seed;
	}

	public override int Next()
	{
		return Next(int.MaxValue);
	}

	public override int Next(int maxValue)
	{
		if (maxValue < 0)
		{
			throw new ArgumentOutOfRangeException("maxValue is less than zero.");
		}
		return (int)((long)(uint)GetNext() * (long)(uint)maxValue >>> 32);
	}

	public override int Next(int minValue, int maxValue)
	{
		if (minValue > maxValue)
		{
			throw new ArgumentOutOfRangeException("minValue is greater than maxValue.");
		}
		return minValue + Next(maxValue - minValue);
	}

	public override double NextDouble()
	{
		return Sample();
	}

	protected override double Sample()
	{
		return (double)Next() / 2147483647.0;
	}
}
internal class DebugUtils
{
	public static void ObjectInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo field in fields)
		{
			FieldPrinter(o, type, field);
		}
	}

	public static void MethodInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		MethodInfo[] methods = type.GetMethods(bindingAttr);
		foreach (MethodInfo methodInfo in methods)
		{
			methodInfo.GetParameters();
			string arg = string.Join(", ", (from x in methodInfo.GetParameters()
				select x.ParameterType?.ToString() + " " + x.Name).ToArray());
			Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})");
		}
	}

	private static void ItemDataInspector(ItemData item)
	{
		ObjectInspector(item);
		ObjectInspector(item.m_shared);
	}

	private static void FieldPrinter(object o, Type t, FieldInfo field)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		try
		{
			if (field.FieldType == typeof(ItemData))
			{
				ItemData val = (ItemData)field.GetValue(o);
				if (val != null)
				{
					ItemDataInspector(val);
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(Transform))
			{
				Transform val2 = (Transform)field.GetValue(o);
				if ((Object)(object)val2 != (Object)null)
				{
					Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name));
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(EffectList))
			{
				EffectList val3 = (EffectList)field.GetValue(o);
				if (val3 != null)
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:");
					EffectData[] effectPrefabs = val3.m_effectPrefabs;
					foreach (EffectData val4 in effectPrefabs)
					{
						Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name));
					}
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else
			{
				Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}");
			}
		}
		catch (Exception)
		{
			Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name));
		}
	}

	public static void GameObjectInspector(GameObject go)
	{
		Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
		ObjectInspector(go);
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			try
			{
				string obj = ((val != null) ? ((Object)val).name : null);
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = val.transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent = transform.parent;
						obj2 = ((parent != null) ? ((Object)parent).name : null);
					}
				}
				Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2));
				ObjectInspector(val);
			}
			catch (Exception)
			{
			}
		}
	}

	public static void PrintList<T>(List<T> l)
	{
		foreach (T item in l)
		{
			Debug.Log((object)item.ToString());
		}
	}

	public static void ComponentInspector(Component c)
	{
		Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name));
		ObjectInspector(c);
	}

	public static void EffectsInspector(EffectList e)
	{
		EffectData[] effectPrefabs = e.m_effectPrefabs;
		Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}");
		EffectData[] array = effectPrefabs;
		foreach (EffectData val in array)
		{
			Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}");
		}
	}

	public static void PrintInventory()
	{
		foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
		{
			Debug.Log((object)allItem.m_shared.m_name);
		}
	}

	public static void PrintAllObjects()
	{
		ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x)
		{
			Debug.Log((object)("GameObject " + ((Object)x).name));
		});
	}

	public static void PrintAllCharacters()
	{
		Character.GetAllCharacters().ForEach(delegate(Character x)
		{
			Debug.Log((object)("Character " + ((Object)x).name));
		});
	}

	public static void PrintAllLayers()
	{
		string[] array = (from index in Enumerable.Range(0, 31)
			select LayerMask.LayerToName(index) into l
			where !string.IsNullOrEmpty(l)
			select l).ToArray();
		foreach (string text in array)
		{
			Debug.Log((object)("Layer " + text + " " + Convert.ToString(LayerMask.NameToLayer(text), 2).PadLeft(32, '0')));
		}
	}
}
public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase
{
	private ConfigEntry<T> _entry;

	private EventHandler rootHandler;

	private Action<object, EventArgs> clientDelegate;

	private Logging Log;

	public ConfigEntry<T> ConfigEntry
	{
		get
		{
			return _entry;
		}
		set
		{
			_entry = value;
			if (_entry != null && rootHandler != null)
			{
				_entry.SettingChanged += rootHandler;
			}
			Name = ((ConfigEntryBase)_entry).Definition.Key;
			Section = ((ConfigEntryBase)_entry).Definition.Section;
			ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
			Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue);
		}
	}

	public T Value
	{
		get
		{
			return _entry.Value;
		}
		set
		{
			_entry.Value = value;
		}
	}

	public DelegatedConfigEntry(bool useServerDelegate = false)
		: this((Action<object, EventArgs>)null, useServerDelegate)
	{
	}

	public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false)
	{
		Log = Logging.GetLogger();
		Log.Trace("DelegatedConfigEntry");
		if (delegateHandler != null)
		{
			clientDelegate = delegateHandler;
		}
		if (useServerDelegate)
		{
			Log.Trace("Configuring server delegate");
			rootHandler = delegate(object s, EventArgs e)
			{
				ServerDelegate(s, e);
			};
			ServerConfiguration.ServerDelegatedEntries.Add(this);
		}
		else if (clientDelegate != null)
		{
			rootHandler = delegate(object s, EventArgs e)
			{
				clientDelegate(s, e);
			};
		}
	}

	private void ServerDelegate(object sender, EventArgs args)
	{
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false && ServerConfiguration.Instance.ReceivedServerValues)
			{
				if (ServerValue != null)
				{
					((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
					Log.Debug("Setting " + Name + " to server value " + ServerValue);
				}
			}
			else if (flag == true)
			{
				ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
				ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args);
			}
		}
		if (clientDelegate != null)
		{
			clientDelegate(sender, args);
		}
		_entry.SettingChanged += rootHandler;
	}

	public void EnableHandler(bool setActive)
	{
		if (setActive)
		{
			_entry.SettingChanged += rootHandler;
		}
		else
		{
			_entry.SettingChanged -= rootHandler;
		}
	}

	public bool IsKeyPressed()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyDown()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyReleased()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}
}
public class DelegatedConfigEntryBase
{
	public string Name;

	public string Section;

	public string ServerValue;
}
internal class HarmonyHelper
{
	public enum PatchType
	{
		Prefix,
		Postfix,
		Transpiler,
		Finalizer
	}

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

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

	public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
		{
			if (Harmony.HasAnyPatches(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from Harmony");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
			else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from BepInEx");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
		}
	}

	public static void AddExclusion(string key)
	{
		if (detectionSet.ContainsKey(key))
		{
			unpatchMods.Add(key, detectionSet[key]);
		}
	}

	public static void UnpatchMods(Harmony harmony)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
		{
			logger.Warning("Not compatible with " + unpatchMod.Value);
			harmony.UnpatchAll(unpatchMod.Key);
			detectionSet.Remove(unpatchMod.Key);
			logger.Warning("Disabled " + unpatchMod.Value);
		}
	}

	public static bool IsModDetected(string key)
	{
		return detectionSet.ContainsKey(key);
	}

	public static bool IsModNameDetected(string value)
	{
		return detectionSet.ContainsValue(value);
	}

	public static bool TryGetDetectedModName(string key, out string mod)
	{
		return detectionSet.TryGetValue(key, out mod);
	}

	public static bool TryGetDetectedModKey(string value, out string key)
	{
		key = null;
		foreach (string key2 in detectionSet.Keys)
		{
			if (detectionSet[key2] == value)
			{
				key = key2;
				return true;
			}
		}
		return false;
	}

	public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null)
	{
		string text = null;
		int num = 0;
		Logging logger = Logging.GetLogger();
		foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
		{
			MethodBaseExtensions.HasMethodBody(item);
			Patches patchInfo = Harmony.GetPatchInfo(item);
			ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes;
			switch (patchType)
			{
			case PatchType.Postfix:
				readOnlyCollection = patchInfo.Postfixes;
				break;
			case PatchType.Prefix:
				readOnlyCollection = patchInfo.Prefixes;
				break;
			case PatchType.Transpiler:
				readOnlyCollection = patchInfo.Transpilers;
				break;
			case PatchType.Finalizer:
				readOnlyCollection = patchInfo.Finalizers;
				break;
			}
			foreach (Patch item2 in readOnlyCollection)
			{
				if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName))
				{
					continue;
				}
				if (patchMethodName != null)
				{
					if (item2.PatchMethod.Name == patchMethodName)
					{
						num++;
						text = item2.owner;
					}
				}
				else
				{
					num++;
					text = item2.owner;
				}
			}
			if (num == 1)
			{
				detectionSet.Add(text, modName);
				logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}");
			}
			else if (num > 1)
			{
				text = null;
				logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify.");
			}
		}
		if (num == 0)
		{
			logger.Info("No patch found for " + modName);
		}
		return text;
	}
}
public class IterativeStopwatch : Stopwatch
{
	private double startMillis;

	private Logging Log = Logging.GetLogger();

	public long Iterations { get; private set; }

	public double IterationMicroseconds { get; private set; }

	public double TotalElapsedMicroseconds { get; private set; }

	public double IterationMilliseconds { get; private set; }

	public double TotalElapsedMilliseconds { get; private set; }

	public double AverageMicroseconds { get; private set; }

	public double AverageMilliseconds { get; private set; }

	public IterativeStopwatch()
	{
		Iterations = 0L;
	}

	public new void Start()
	{
		startMillis = base.Elapsed.TotalMilliseconds;
		base.Start();
	}

	public new void Stop()
	{
		if (base.IsRunning)
		{
			base.Stop();
			Iterations++;
			IterationMilliseconds = base.Elapsed.TotalMilliseconds - startMillis;
			IterationMicroseconds = IterationMilliseconds * 1000.0;
			TotalElapsedMilliseconds = base.Elapsed.TotalMilliseconds;
			TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0;
			AverageMilliseconds = TotalElapsedMilliseconds / (double)Iterations;
			AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations;
		}
	}

	public new void Reset()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Reset();
	}

	public new void Restart()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Restart();
	}
}
public class Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

	private Logging(LogLevels level, string name)
	{
		LogLevel = level;
		ModName = name;
	}

	public static Logging GetLogger(LogLevels level, string name)
	{
		if (_logger == null)
		{
			_logger = new Logging(level, name);
		}
		return _logger;
	}

	public static Logging GetLogger()
	{
		if (_logger == null)
		{
			throw new NullReferenceException("Logger not initialized");
		}
		return _logger;
	}

	public void Trace(string msg)
	{
		if (LogLevel >= LogLevels.Trace)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Debug(string msg)
	{
		if (LogLevel >= LogLevels.Debug)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Info(string msg)
	{
		if (LogLevel >= LogLevels.Info)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Warning(string msg)
	{
		if (LogLevel >= LogLevels.Warning)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(string msg)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(Exception e)
	{
		Error(e, stackTrace: false);
	}

	public void Error(Exception e, bool stackTrace)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Warning(Message(e.Message));
			if (stackTrace)
			{
				Warning(e.StackTrace);
			}
		}
	}

	public void Critical(Exception e)
	{
		if (LogLevel >= LogLevels.Critical)
		{
			Debug(Message(e.Message));
			Error(e.StackTrace);
		}
	}

	private string Message(string msg)
	{
		return ModName + ": " + msg;
	}

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "StopAll")]
	private static class ZNet_Shutdown_Patch
	{
		[HarmonyPrefix]
		private static void ZNet_StopAll_Prefix(ZNet __instance)
		{
			Log.Debug("ZNet_StopAll_Patch_Prefix");
			Instance.ReceivedServerValues = false;
		}
	}

	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			Log.Debug("ZNet OnNewConnection postfix");
			if (!__instance.IsServer())
			{
				try
				{
					peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)Instance.RPC_ClientConfigReceiver);
					Log.Debug("Player registered RPC_ClientConfigReceiver");
					return;
				}
				catch (Exception)
				{
					Log.Warning("Failed to register RPC");
					return;
				}
			}
			try
			{
				Instance.SendConfigToClient(peer);
			}
			catch (Exception)
			{
				Log.Warning("Error sending server configuration to client");
			}
		}
	}

	public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>();

	private static ConfigFile LocalConfig;

	private static BaseUnityPlugin Mod;

	private static string ConfigFileName;

	private static ServerConfiguration _instance;

	private static Logging Log;

	public bool IsSetup;

	public bool ReceivedServerValues;

	public FileSystemWatcher ConfigWatcher;

	private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first.";

	public static ServerConfiguration Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ServerConfiguration();
			}
			return _instance;
		}
	}

	private ServerConfiguration()
	{
	}

	public void Setup(ConfigFile config, BaseUnityPlugin modInstance)
	{
		LocalConfig = config;
		Log = Logging.GetLogger();
		Log.Trace("ServerConfiguration Setup");
		Mod = modInstance;
		ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		IsSetup = true;
	}

	public void CreateConfigWatcher()
	{
		ConfigWatcher = Utils.CreateFileWatcher(LocalConfig.ConfigFilePath, LoadConfig);
	}

	private void LoadConfig(object sender, FileSystemEventArgs e)
	{
		if (!File.Exists(LocalConfig.ConfigFilePath))
		{
			return;
		}
		try
		{
			Log.Debug($"Loading configuration {e.ChangeType}");
			LocalConfig.Reload();
		}
		catch
		{
			Log.Error("Error loading configuration file " + ConfigFileName);
		}
	}

	public static string GetPluginGuid()
	{
		return Mod.Info.Metadata.GUID;
	}

	public void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
	{
		if (!Instance.IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ClientConfigReceiver");
		string section;
		string name;
		while (package.GetPos() < package.Size())
		{
			section = package.ReadString();
			name = package.ReadString();
			string text = package.ReadString();
			Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage");
			DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section);
			if (delegatedConfigEntryBase != null)
			{
				Log.Trace("Found DCEB on client and setting to server value " + text);
				delegatedConfigEntryBase.ServerValue = text;
			}
			ConfigEntryBase val = LocalConfig[section, name];
			if (val != null)
			{
				Log.Trace("Found local CEB and setting underlying config value " + text);
				val.SetSerializedValue(text);
			}
		}
		ReceivedServerValues = true;
	}

	internal void WriteConfigEntries(ZPackage zpkg)
	{
		foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries)
		{
			Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage");
			zpkg.Write(serverDelegatedEntry.Section);
			zpkg.Write(serverDelegatedEntry.Name);
			zpkg.Write(serverDelegatedEntry.ServerValue);
		}
	}

	internal void SendConfigToClient(ZNetPeer peer)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		if (!Instance.IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("SendConfigToClient");
		ZPackage val = new ZPackage();
		WriteConfigEntries(val);
		peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
		Log.Trace("Invoked ClientConfigReceiver on peer");
	}

	public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
		}
		else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0)
		{
			Log.Debug("SendConfigToAllClients");
			ZPackage zpkg = new ZPackage();
			WriteConfigEntries(zpkg);
			((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg));
		}
	}

	private IEnumerator Co_BroadcastConfig(ZPackage zpkg)
	{
		Log.Debug("Co_BroadcastConfig");
		List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
		foreach (ZNetPeer item in connectedPeers)
		{
			if (item != ZNet.instance.GetServerPeer())
			{
				item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg });
				Log.Trace("Invoked ClientConfigReceiver on peer");
			}
			yield return null;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

	public static int Guardrails(int value, int lbound, int ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string truncate(string value, int maxChars)
	{
		if (value == null)
		{
			return null;
		}
		if (value.Length <= maxChars)
		{
			return value;
		}
		return value.Substring(0, maxChars);
	}

	public static void GetCharactersInRangeXZ(Vector3 point, float radius, List<Character> characters)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		float num = radius * radius;
		foreach (Character s_character in Character.s_characters)
		{
			if (DistanceSqrXZ(((Component)s_character).transform.position, point) < num)
			{
				characters.Add(s_character);
			}
		}
	}

	public static float DistanceSqr(Vector3 v0, Vector3 v1)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		float num = v1.x - v0.x;
		float num2 = v1.y - v0.y;
		float num3 = v1.z - v0.z;
		return num * num + num2 * num2 + num3 * num3;
	}

	public static float DistanceSqrXZ(Vector3 v0, Vector3 v1)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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)
		float num = v1.x - v0.x;
		float num2 = v1.z - v0.z;
		return num * num + num2 * num2;
	}

	public static float DistanceXZ(Vector3 v0, Vector3 v1)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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)
		float num = v1.x - v0.x;
		float num2 = v1.z - v0.z;
		return Mathf.Sqrt(num * num + num2 * num2);
	}

	public static float Guardrails(float value, float lbound, float ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string UnClonifiedName(string name)
	{
		if (name == null)
		{
			return null;
		}
		int num = name.IndexOf("(Clone)");
		if (num < 1)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	public static void SetTranslator(int id, string idText)
	{
		typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2]
		{
			"skill_" + id,
			idText
		});
	}

	public static string GetTranslated(int id)
	{
		Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id)));
		return Localization.instance.Localize("$skill_" + id);
	}

	public static string GetAssemblyPathedFile(string fileName)
	{
		return new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName.Replace('\\', '/') + "/" + fileName;
	}

	public static Sprite GetPrefabIcon(string prefabName)
	{
		Sprite result = null;
		GameObject prefab = GetPrefab(prefabName);
		ItemDrop val = default(ItemDrop);
		if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref val))
		{
			result = val.m_itemData.GetIcon();
		}
		return result;
	}

	public static Player GetPlayerByZDOID(ZDOID zid)
	{
		//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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			ZDOID zDOID = ((Character)allPlayer).GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(zid))
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(string cid)
	{
		//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)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(ZDOID cid)
	{
		//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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static ZNetPeer GetPeerByRPC(ZRpc rpc)
	{
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfType(Type t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		List<GameObject> list = new List<GameObject>();
		Object[] array = Object.FindObjectsOfType(t);
		foreach (Object val in array)
		{
			list.Add(((Component)val).gameObject);
		}
		return list;
	}

	public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0];
	}

	public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius)
	{
		//IL_0007: 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)
		List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>();
		List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius);
		if (gameObjectsOfTypeInRange.Count > 0)
		{
			foreach (GameObject item in gameObjectsOfTypeInRange)
			{
				list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point)));
			}
			list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value));
			return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key);
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		return (from x in GetGameObjectsOfType(t)
			where Vector3.Distance(x.transform.position, point) < radius
			select x).ToList();
	}

	public static float GetPointDepth(Vector3 p)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p);
	}

	public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter)
	{
		List<string> list = new List<string>();
		string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			list.Add(text.Trim());
		}
		return list;
	}

	public static float GetSolidHeight(Vector3 p)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		int solidRayMask = ZoneSystem.instance.m_solidRayMask;
		float result = 0f;
		p.y += 1000f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody))
		{
			result = ((RaycastHit)(ref val)).point.y;
		}
		return result;
	}

	public static Transform FindChild(Transform aParent, string aName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		foreach (Transform item in aParent)
		{
			Transform val = item;
			if (((Object)val).name == aName)
			{
				return val;
			}
			Transform val2 = FindChild(val, aName);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	public static Transform FindParent(Transform go)
	{
		while ((Object)(object)go.parent != (Object)null)
		{
			go = go.parent;
		}
		return go;
	}

	public static GameObject GetPrefab(int prefabHash)
	{
		return GetPrefabByHash(prefabHash);
	}

	public static GameObject GetPrefabByHash(int prefabHash)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found prefab in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabHash) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in Scene");
			}
		}
		return val;
	}

	public static GameObject GetPrefab(string prefabName)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabName);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found " + prefabName + " in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found " + prefabName + " in Scene");
			}
		}
		return val;
	}

	public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return null;
		}
		IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp)
		{
			KeyValuePair<K, V> keyValuePair = kvp;
			string? obj = keyValuePair.Key?.ToString();
			string text = delimc;
			keyValuePair = kvp;
			return obj + text + keyValuePair.Value;
		});
		return string.Join(delimp, values);
	}

	public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return;
		}
		dict.Clear();
		string[] separator = new string[1] { delimp };
		string[] separator2 = new string[1] { delimc };
		string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length == 2)
			{
				dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1]));
			}
		}
	}

	public static FileSystemWatcher CreateFileWatcher(string fullPath, FileSystemEventHandler handler)
	{
		string fileName = Path.GetFileName(fullPath);
		FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(fullPath.Substring(0, fullPath.Length - fileName.Length), fileName);
		fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
		fileSystemWatcher.Changed += handler;
		fileSystemWatcher.Created += handler;
		fileSystemWatcher.IncludeSubdirectories = false;
		fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileSystemWatcher.EnableRaisingEvents = true;
		return fileSystemWatcher;
	}

	public static T TypedValue<T>(object a)
	{
		return (T)Convert.ChangeType(a, typeof(T));
	}

	public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall)
	{
		float num = elapsedTime / duration;
		if (num <= pctFromStartRise)
		{
			return maxValue * (num / pctFromStartRise);
		}
		if (num >= 1f - pctFromEndFall)
		{
			return maxValue * ((1f - num) / pctFromEndFall);
		}
		return maxValue;
	}

	public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		Logging logger = Logging.GetLogger();
		Type type = ((object)original).GetType();
		logger.Debug($"Original Type is {type}");
		GameObject obj = destination;
		logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null));
		Component val = destination.GetComponent(type);
		if ((Object)(object)val == (Object)null)
		{
			val = destination.AddComponent(type);
		}
		if ((Object)(object)val == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		Component val2 = (Component)Activator.CreateInstance(type);
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Boxed component is null");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(val2, fieldInfo.GetValue(original));
		}
		val = val2;
		return true;
	}

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
internal class Cfg
{
	public static DelegatedConfigEntry<int> displacementChance;

	public static DelegatedConfigEntry<int> maxPieceDamage;

	public static DelegatedConfigEntry<int> maxTreeDamage;

	public static DelegatedConfigEntry<bool> allowFullDestruction;

	public static DelegatedConfigEntry<float> faultChance;

	public static DelegatedConfigEntry<bool> activeWardsPreventDamage;

	public static DelegatedConfigEntry<bool> activeShieldsPreventDamage;

	public static DelegatedConfigEntry<bool> monstersFlee;

	public static DelegatedConfigEntry<bool> showDust;

	public static DelegatedConfigEntry<bool> charactersStagger;

	public static DelegatedConfigEntry<bool> hookedItemsFall;

	public static DelegatedConfigEntry<bool> activeItemsMove;

	public static DelegatedConfigEntry<int> earthquakeRadius;

	public static DelegatedConfigEntry<bool> cameraShakeOverride;

	public static DelegatedConfigEntry<int> cameraShakeIntensity;

	public static DelegatedConfigEntry<int> cameraShakeFrequency;

	public static DelegatedConfigEntry<bool> biomeMeadows;

	public static DelegatedConfigEntry<bool> biomeSwamp;

	public static DelegatedConfigEntry<bool> biomeBlackForest;

	public static DelegatedConfigEntry<bool> biomeMistlands;

	public static DelegatedConfigEntry<bool> biomeAshlands;

	public static DelegatedConfigEntry<bool> biomeDeepNorth;

	public static DelegatedConfigEntry<bool> biomeMountains;

	public static DelegatedConfigEntry<bool> biomePlains;

	public static DelegatedConfigEntry<float> fissureMaxDepth;

	public static DelegatedConfigEntry<float> fissureDeepenPct;

	public static DelegatedConfigEntry<int> minInterval;

	public static DelegatedConfigEntry<int> maxInterval;

	public static DelegatedConfigEntry<Logging.LogLevels> debugLevel;

	public static void BepInExConfig(BaseUnityPlugin _instance)
	{
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Expected O, but got Unknown
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0385: Expected O, but got Unknown
		//IL_0442: Unknown result type (might be due to invalid IL or missing references)
		//IL_044c: Expected O, but got Unknown
		//IL_048b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0495: 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_0521: Unknown result type (might be due to invalid IL or missing references)
		//IL_052b: Expected O, but got Unknown
		//IL_056e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Expected O, but got Unknown
		//IL_0641: Unknown result type (might be due to invalid IL or missing references)
		//IL_064b: Expected O, but got Unknown
		//IL_0684: Unknown result type (might be due to invalid IL or missing references)
		//IL_068e: Expected O, but got Unknown
		ServerConfiguration.Instance.Setup(_instance.Config, _instance);
		debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging);
		debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log");
		Valquake.Log.LogLevel = debugLevel.Value;
		biomeMeadows = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeMeadows.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Meadows", true, "Earthquakes trigger in the Meadows.@");
		biomeSwamp = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeSwamp.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Swamp", false, "Earthquakes trigger in the Swamp.@");
		biomeBlackForest = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeBlackForest.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Black Forest", false, "Earthquakes trigger in the Black Forest.@");
		biomeMountains = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeMountains.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Mountains", true, "Earthquakes trigger in the Mountains.@");
		biomePlains = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomePlains.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Plains", false, "Earthquakes trigger in the Plains.@");
		biomeMistlands = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeMistlands.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Mistlands", true, "Earthquakes trigger in the Mistlands.@");
		biomeAshlands = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeAshlands.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Ashlands", true, "Earthquakes trigger in the Ashlands.@");
		biomeDeepNorth = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		biomeDeepNorth.ConfigEntry = _instance.Config.Bind<bool>("Biomes", "Deep North", false, "Earthquakes trigger in the Deep North.@");
		showDust = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showDust.ConfigEntry = _instance.Config.Bind<bool>("Effects", "A. Show Dust", true, "If enabled, will display a cloud of dust along the fault line during a quake. Only meaningful if Fissure Chance is > 0%.@");
		monstersFlee = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		monstersFlee.ConfigEntry = _instance.Config.Bind<bool>("Effects", "B. Creatures Scatter", true, "If enabled, creatures close enough to quake zone will scatter for a short time.@");
		charactersStagger = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		charactersStagger.ConfigEntry = _instance.Config.Bind<bool>("Effects", "C. Staggering", true, "If enabled, players and creatures can stagger during the quake while inside the quake zone.@");
		allowFullDestruction = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		allowFullDestruction.ConfigEntry = _instance.Config.Bind<bool>("Effects", "D. Allow Piece Destruction", false, "If enabled, allows the full destruction of pieces duing the quake (dropping materials). If disabled, pieces can only be reduced to 1 health.@");
		displacementChance = new DelegatedConfigEntry<int>(useServerDelegate: true);
		displacementChance.ConfigEntry = _instance.Config.Bind<int>("Effects", "E. Piece Displacement Chance", 0, new ConfigDescription("The percent chance pieces are displaced in the horizontal plane during a quake. A value of zero (0) never displaces pieces.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		hookedItemsFall = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		hookedItemsFall.ConfigEntry = _instance.Config.Bind<bool>("Effects", "F. Items Can Fall", true, "If enabled, things mounted on items stands can be shaken loose and fall during a quake.@");
		activeItemsMove = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		activeItemsMove.ConfigEntry = _instance.Config.Bind<bool>("Effects", "G. Things Can Move", true, "If enabled, some 'active' things like carts & ships, will move with the quake.@");
		earthquakeRadius = new DelegatedConfigEntry<int>(useServerDelegate: true);
		earthquakeRadius.ConfigEntry = _instance.Config.Bind<int>("Control", "A. Quake Radius", 100, new ConfigDescription("Radius (in meters) of the earthquake zone. Effects will diminish farther from the epicenter.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 200), Array.Empty<object>()));
		minInterval = new DelegatedConfigEntry<int>(Valquake.ChangeMinInterval, useServerDelegate: true);
		minInterval.ConfigEntry = _instance.Config.Bind<int>("Control", "B. Min Interval", 30, "Minimum possible time (in minutes) between earthquakes. Minimum value is 1.@");
		maxInterval = new DelegatedConfigEntry<int>(Valquake.ChangeMaxInterval, useServerDelegate: true);
		maxInterval.ConfigEntry = _instance.Config.Bind<int>("Control", "C. Max Interval", 120, "Maximum possible time (in minutes) between earthquakes. Value must be equal to or greater than Min Interval.@");
		faultChance = new DelegatedConfigEntry<float>(useServerDelegate: true);
		faultChance.ConfigEntry = _instance.Config.Bind<float>("Control", "D. Fault Zone Chance", 20f, new ConfigDescription("The percent chance of a zone having a 'fault line'. Quakes will only create a fissure in a zone with a fault line. A value of 0% will prevent any fissures from forming.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
		maxPieceDamage = new DelegatedConfigEntry<int>(useServerDelegate: true);
		maxPieceDamage.ConfigEntry = _instance.Config.Bind<int>("Control", "E. Max Piece Damage", 1000, new ConfigDescription("The maximum damage that can be applied to pieces in the quake zone. A value of 0 will not apply any damage. Damage is attenuated by distance from the epicenter and degree of support.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000), Array.Empty<object>()));
		maxTreeDamage = new DelegatedConfigEntry<int>(useServerDelegate: true);
		maxTreeDamage.ConfigEntry = _instance.Config.Bind<int>("Control", "F. Max Tree Damage", 200, new ConfigDescription("The maximum damage that can be applied to trees in the quake zone. A value of 0 will not apply any damage. Damage is attenuated by distance from the epicenter.@", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
		fissureMaxDepth = new DelegatedConfigEntry<float>(useServerDelegate: true);
		fissureMaxDepth.ConfigEntry = _instance.Config.Bind<float>("Control", "G. Max Fissure Depth", 2f, new ConfigDescription("The maximum depth (in meters) of the fissure for the first quake along a fault line. Subsequent quakes along the same fault line are controlled by Successive Quake Depth as a percentage of this value.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
		fissureDeepenPct = new DelegatedConfigEntry<float>(useServerDelegate: true);
		fissureDeepenPct.ConfigEntry = _instance.Config.Bind<float>("Control", "H. Successive Quake Depth", 0.2f, new ConfigDescription("Sets the percent of the Max Fissure Depth to apply to each successive quake along the same fault line. A value of 0% will not deepen the fissure.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		activeWardsPreventDamage = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		activeWardsPreventDamage.ConfigEntry = _instance.Config.Bind<bool>("Control", "I. Active Wards Reduce Damage", false, "If enabled, an active ward will reduce damage to pieces if the quake epicenter is within the ward's area of protection.@");
		activeShieldsPreventDamage = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		activeShieldsPreventDamage.ConfigEntry = _instance.Config.Bind<bool>("Control", "J. Active Shields Reduce Damage", false, "If enabled, a fueled Shield Generator will reduce damage to pieces if the quake epicenter is within the shield's area of protection.@");
		cameraShakeOverride = new DelegatedConfigEntry<bool>();
		cameraShakeOverride.ConfigEntry = _instance.Config.Bind<bool>("Camera", "Camera Sway Override", false, "If enabled, will override Valheim's camera shake setting (just for quakes) and 'sway' camera. If disabled, will use Valheim's setting.");
		cameraShakeIntensity = new DelegatedConfigEntry<int>();
		cameraShakeIntensity.ConfigEntry = _instance.Config.Bind<int>("Camera", "Camera Sway Intensity", 100, new ConfigDescription("Sets how much the camera 'sways'. Lower values will reduce the amount of camera movement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		cameraShakeFrequency = new DelegatedConfigEntry<int>();
		cameraShakeFrequency.ConfigEntry = _instance.Config.Bind<int>("Camera", "Camera Sway Frequency", 10, new ConfigDescription("Sets how fast the camera 'sways'. Lower values will reduce how quickly the camera moves.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
		ServerConfiguration.Instance.CreateConfigWatcher();
	}
}
public class QuakeShaker
{
	private float angle;

	public static float s_baseIntensity = 3f;

	public static float PctRise = 0.2f;

	public static float PctFall = 0.5f;

	private const float twoPi = (float)Math.PI * 2f;

	private float lastTime;

	public Vector3 Epicenter { get; set; }

	public float Frequency { get; set; }

	public float Duration { get; set; }

	public float Intensity { get; set; }

	public float Radius { get; set; }

	private float StopTime { get; set; }

	public QuakeShaker(Vector3 epicenter, float radius, float intensity, float duration, float frequency = 30f)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		Epicenter = epicenter;
		Frequency = frequency;
		Duration = duration;
		Intensity = intensity;
		Radius = radius;
		StopTime = 0f;
	}

	public bool isActive()
	{
		return Time.time < StopTime;
	}

	public void Start()
	{
		StopTime = Time.time + Duration;
	}

	public void Stop()
	{
		StopTime = 0f;
	}

	public float PctOfDuration()
	{
		return 1f - (StopTime - Time.time) / Duration;
	}

	public bool HasPeaked()
	{
		return PctOfDuration() >= PctRise;
	}

	public bool InPeakWindow()
	{
		float num = PctOfDuration();
		if (num >= PctRise)
		{
			return num <= PctFall;
		}
		return false;
	}

	public float ElapsedTime()
	{
		return Time.time + Duration - StopTime;
	}

	public float TimeRemaining()
	{
		return StopTime - Time.time;
	}

	public float TimeAdjustedIntensity()
	{
		return Utils.TimeAdjustedRamp(Intensity, Duration, ElapsedTime(), PctRise, PctFall);
	}

	public float GetCurrentAngle()
	{
		return angle;
	}

	public void Update(float dt)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		if (!isActive())
		{
			lastTime = 0f;
			return;
		}
		GameCamera instance = GameCamera.instance;
		float time = Time.time;
		if (lastTime != 0f)
		{
			dt = time - lastTime;
		}
		lastTime = time;
		float num = (float)Cfg.cameraShakeIntensity.Value / 100f;
		float num2 = TimeAdjustedIntensity() * num;
		angle += dt * Frequency;
		if (angle > (float)Math.PI * 2f)
		{
			angle -= (float)Math.PI * 2f;
		}
		Quaternion val = Quaternion.Euler(Mathf.Sin(angle) * num2, 0f, Mathf.Cos(angle * 0.9f) * num2);
		((Component)instance).transform.rotation = ((Component)instance).transform.rotation * val;
	}
}
[BepInPlugin("neobotics.valheim_mod.valquake", "Valquake", "0.1.5")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class Valquake : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Heightmap), "Regenerate")]
	private static class Heightmap_Regenerate_Patch
	{
		[HarmonyPrefix]
		private static bool Heightmap_Regenerate_Prefix(Heightmap __instance)
		{
			if (isCracking)
			{
				Log.Trace("Skipping Regenerate until fissure complete");
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(AnimalAI), "UpdateAI")]
	private static class AnimalAI_UpdateAI_Patch
	{
		[HarmonyPrefix]
		private static bool AnimalAI_UpdateAI_Prefix(AnimalAI __instance, float dt)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (IsShaking() && Vector3.Distance(((Component)__instance).transform.position, quakeShaker.Epicenter) < quakeShaker.Radius)
			{
				((BaseAI)__instance).SetAlerted(true);
				((BaseAI)__instance).Flee(dt, quakeShaker.Epicenter);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
	private static class MonsterAI_UpdateAI_Patch
	{
		[HarmonyPrefix]
		private static bool MonsterAI_UpdateAI_Prefix(MonsterAI __instance, float dt)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (IsShaking() && Vector3.Distance(((Component)__instance).transform.position, quakeShaker.Epicenter) < quakeShaker.Radius * 0.75f)
			{
				((BaseAI)__instance).SetAlerted(true);
				((BaseAI)__instance).Flee(dt, quakeShaker.Epicenter);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Game), "Start")]
	private static class Game_Start_Patch
	{
		[HarmonyPostfix]
		private static void Game_Start_Patch_Postfix(Game __instance)
		{
			Log.Debug("Game_Start_Patch_Postfix");
			audioHelper = ((Component)__instance).gameObject.AddComponent<AudioHelper>();
			ZRoutedRpc.instance.Register<Vector3, float, float, float>("ValquakeShake", (Method<Vector3, float, float, float>)RPC_ValquakeShake);
			Log.Debug(string.Format("Registered RPC ValquakeShake {0}", StringExtensionMethods.GetStableHashCode("ValquakeShake")));
			ZRoutedRpc.instance.Register("ValquakeReset", (Action<long>)RPC_ValquakeReset);
			Log.Debug(string.Format("Registered RPC ValquakeReset {0}", StringExtensionMethods.GetStableHashCode("ValquakeReset")));
		}
	}

	[HarmonyPatch(typeof(Game), "Logout")]
	private static class Game_Logout_Patch
	{
		[HarmonyPrefix]
		private static void Game_Logout_Patch_Prefix(Game __instance)
		{
			nextQuakeTime = 0f;
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	public static class Player_Update_Patch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && nextQuakeTime > 0f && Time.time > nextQuakeTime)
			{
				StartQuake();
			}
		}
	}

	[HarmonyPatch(typeof(GameCamera), "UpdateCameraShake")]
	private static class GameCamera_UpdateCameraShake_Patch
	{
		[HarmonyPostfix]
		private static void GameCamera_UpdateCameraShake_Postfix(GameCamera __instance, float dt)
		{
			if (quakeShaker != null)
			{
				quakeShaker.Update(dt);
				if (!quakeShaker.isActive())
				{
					quakeShaker = null;
				}
			}
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	public static class Player_OnSpawned_Patch
	{
		public static void Postfix(Player __instance)
		{
			Log.Debug("Player_OnSpawned_Patch_Postfix");
			SetNextQuake(Cfg.minInterval.Value, Cfg.maxInterval.Value);
		}
	}

	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	private static class Terminal_InitTerminal_Patch
	{
		[HarmonyPostfix]
		private static void Terminal_InitTerminal_Postfix(Terminal __instance)
		{
			AddValquakeConsoleCommand();
		}
	}

	[HarmonyPatch(typeof(ItemStand), "DropItem")]
	private static class ItemStand_DropItem_Patch
	{
		[HarmonyPrefix]
		private static bool ItemStand_DropItem_Prefix(ItemStand __instance)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (!IsShaking())
			{
				return true;
			}
			Log.Debug("ItemStand_DropItem_Patch_Prefix");
			if (!__instance.HaveAttachment())
			{
				return false;
			}
			GameObject prefab = Utils.GetPrefab(__instance.m_nview.GetZDO().GetString(ZDOVars.s_item, ""));
			if (Object.op_Implicit((Object)(object)prefab))
			{
				Vector3 val = Vector3.zero;
				Quaternion val2 = Quaternion.identity;
				Transform val3 = prefab.transform.Find("attach");
				if (Object.op_Implicit((Object)(object)prefab.transform.Find("attachobj")) && Object.op_Implicit((Object)(object)val3))
				{
					val2 = ((Component)val3).transform.localRotation;
					val = ((Component)val3).transform.localPosition;
				}
				GameObject obj = Object.Instantiate<GameObject>(prefab, __instance.m_dropSpawnPoint.position + val, __instance.m_dropSpawnPoint.rotation * val2);
				obj.GetComponent<ItemDrop>().LoadFromExternalZDO(__instance.m_nview.GetZDO());
				obj.GetComponent<Rigidbody>().rotation = Quaternion.Euler(0.3f, 0.1f, 0.5f);
			}
			__instance.m_nview.GetZDO().Set(ZDOVars.s_item, "");
			__instance.m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3] { "", 0, 0 });
			return false;
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")]
	private static class TerrainComp_RaiseTerrain_Patch
	{
		[HarmonyPrefix]
		private static bool TerrainComp_RaiseTerrain_Prefix(TerrainComp __instance, Vector3 worldPos, float radius, float delta, bool square, float power)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (isCracking)
			{
				DigFissure(__instance, __instance.m_hmap, __instance.m_width, worldPos, radius, delta, square, power);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(TreeBase), "Awake")]
	private static class TreeBase_Awake_Patch
	{
		[HarmonyPostfix]
		private static void TreeBase_Awake_Postfix(TreeBase __instance)
		{
			ZDO val = __instance?.m_nview?.m_zdo;
			if (val != null && !treeManager.ContainsKey(val))
			{
				treeManager.Add(val, __instance);
			}
		}
	}

	[HarmonyPatch(typeof(ZNetScene), "Destroy")]
	private static class ZNetScene_Destroy_Patch
	{
		[HarmonyPrefix]
		private static void ZNetScene_Destroy_Prefix(ZNetScene __instance, GameObject go)
		{
			ZNetView val = default(ZNetView);
			if (go.TryGetComponent<ZNetView>(ref val) && val.m_zdo != null && treeManager.Remove(val.m_zdo))
			{
				Log.Trace("Removed tree from manager");
			}
		}
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static ConsoleEvent <>9__33_0;

		public static Func<bool> <>9__36_0;

		public static Func<bool> <>9__41_0;

		public static Func<bool> <>9__42_0;

		public static Func<bool> <>9__43_0;

		public static Func<bool> <>9__47_0;

		public static Func<bool> <>9__56_0;

		internal void <AddValquakeConsoleCommand>b__33_0(ConsoleEventArgs <p0>)
		{
			if (OkToQuake(Player.m_localPlayer))
			{
				StartQuake();
			}
		}

		internal bool <Co_Clatter>b__36_0()
		{
			return quakeShaker.HasPeaked();
		}

		internal bool <Co_DropAttachedPieces>b__41_0()
		{
			return quakeShaker.HasPeaked();
		}

		internal bool <Co_DamagePieces>b__42_0()
		{
			return quakeShaker.HasPeaked();
		}

		internal bool <Co_DamageTrees>b__43_0()
		{
			return quakeShaker.HasPeaked();
		}

		internal bool <Co_StaggerController>b__47_0()
		{
			return halfCracked;
		}

		internal bool <Co_ModifyTerrain>b__56_0()
		{
			return quakeShaker.HasPeaked();
		}
	}

	internal static Valquake _modInstance;

	private static string Mod = "Valquake";

	private static string LcMod = Mod.ToLower();

	public static Logging Log;

	public static float nextQuakeTime = 0f;

	public static QuakeShaker quakeShaker = null;

	public static bool isCracking = false;

	public static bool halfCracked = false;

	internal static AudioHelper audioHelper;

	internal static GameObject fissure_vfx;

	internal static GameObject cracking_sfx;

	internal static Vector2Int lastFissureXY = Vector2Int.zero;

	internal static Vector3 lastWorldPos = Vector3.zero;

	private const float delayUntilPeak = 2f;

	private static float fissureRadius = 1f;

	private static float fissureSpacing = 1f;

	public static float baseCamShakeFrequency = 10f;

	private const string vfx_fissure_prefab = "vfx_Place_mud_road";

	private const string sfx_crack_prefab = "sfx_stonegolem_attack_hit";

	private const string sfx_rumble = "quake_outdoor_major.mp3";

	private const string sfx_clatter = "clatter.mp3";

	private const string sfx_clunk = "clunk.mp3";

	public static Dictionary<ZDO, TreeBase> treeManager = new Dictionary<ZDO, TreeBase>();

	private static Harmony harmony = null;

	private static int doN = 1;

	public static Valquake GetInstance()
	{
		return _modInstance;
	}

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		_modInstance = this;
		harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		ConfigureMod();
		Log.Info("Awake");
	}

	private void ConfigureMod()
	{
		Log = Logging.GetLogger(Logging.LogLevels.Info, Mod);
		Cfg.BepInExConfig((BaseUnityPlugin)(object)_modInstance);
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	public static void ChangeMinInterval(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		Log.Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		if (Cfg.minInterval.Value < 1)
		{
			Log.Info("Min Interval must be >= 1");
			Cfg.minInterval.Value = 1;
		}
		if (Cfg.maxInterval.Value < Cfg.minInterval.Value)
		{
			Cfg.maxInterval.Value = Cfg.minInterval.Value;
		}
	}

	public static void ChangeMaxInterval(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		Log.Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		if (Cfg.maxInterval.Value < 1 || Cfg.maxInterval.Value < Cfg.minInterval.Value)
		{
			Log.Info("Max Interval must be >= the Min Interval");
			Cfg.maxInterval.Value = Cfg.minInterval.Value;
		}
	}

	private static void SetFissureTerrainOpSettings(Settings settings, float radius, float delta)
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		settings.m_levelOffset = delta;
		settings.m_level = false;
		settings.m_levelRadius = radius;
		settings.m_square = true;
		settings.m_raise = true;
		settings.m_raiseRadius = radius;
		settings.m_raisePower = 0f;
		settings.m_raiseDelta = delta;
		settings.m_smooth = false;
		settings.m_smoothRadius = radius;
		settings.m_smoothPower = 1f;
		settings.m_paintCleared = false;
		settings.m_paintHeightCheck = false;
		settings.m_paintType = (PaintType)0;
		settings.m_paintRadius = radius;
	}

	private static bool InQuakeBiome(Player aPlayer)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Invalid comparison between Unknown and I4
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected I4, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Invalid comparison between Unknown and I4
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Invalid comparison between Unknown and I4
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		Biome currentBiome = aPlayer.GetCurrentBiome();
		if ((int)currentBiome <= 16)
		{
			switch (currentBiome - 1)
			{
			default:
				if ((int)currentBiome != 8)
				{
					if ((int)currentBiome != 16)
					{
						break;
					}
					return Cfg.biomePlains.Value;
				}
				return Cfg.biomeBlackForest.Value;
			case 0:
				return Cfg.biomeMeadows.Value;
			case 1:
				return Cfg.biomeSwamp.Value;
			case 3:
				return Cfg.biomeMountains.Value;
			case 2:
				break;
			}
		}
		else
		{
			if ((int)currentBiome == 32)
			{
				return Cfg.biomeAshlands.Value;
			}
			if ((int)currentBiome == 64)
			{
				return Cfg.biomeDeepNorth.Value;
			}
			if ((int)currentBiome == 512)
			{
				return Cfg.biomeMistlands.Value;
			}
		}
		return false;
	}

	private static void AddValquakeConsoleCommand()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		if (!Terminal.m_terminalInitialized)
		{
			return;
		}
		object obj = <>c.<>9__33_0;
		if (obj == null)
		{
			ConsoleEvent val = delegate
			{
				if (OkToQuake(Player.m_localPlayer))
				{
					StartQuake();
				}
			};
			<>c.<>9__33_0 = val;
			obj = (object)val;
		}
		new ConsoleCommand("valquake", "Starts an earthquake near the player location", (ConsoleEvent)obj, true, false, false, true, false, (ConsoleOptionsFetcher)null, false, false, false);
	}

	private static bool IsShaking()
	{
		if (quakeShaker != null)
		{
			return quakeShaker.isActive();
		}
		return false;
	}

	private static void StartQuake()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("StartQuake");
		Player localPlayer = Player.m_localPlayer;
		nextQuakeTime += (float)Cfg.maxInterval.Value * 60f;
		if (!OkToQuake(localPlayer))
		{
			Log.Debug("Not OK to start quake. Resetting");
			SetNextQuake(5f, 15f);
			return;
		}
		float s_baseIntensity = QuakeShaker.s_baseIntensity;
		float num = audioHelper.GetClipDuration("quake_outdoor_major.mp3");
		if (num <= 0f)
		{
			num = 11f;
		}
		float num2 = Cfg.earthquakeRadius.Value;
		Heightmap val = Heightmap.FindHeightmap(((Component)localPlayer).transform.position);
		Vector3 position = ((Component)val).transform.position;
		audioHelper.Play(position, "quake_outdoor_major.mp3");
		if (localPlayer.InShelter())
		{
			((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_Clatter(((Component)localPlayer).transform.position, 2f));
		}
		ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ValquakeShake", new object[4] { position, num2, s_baseIntensity, num });
		DamageThings(position, Cfg.earthquakeRadius.Value, num);
		bool flag = true;
		if (Cfg.faultChance.Value > 0f)
		{
			flag = CreateFissure(val);
		}
		if (flag)
		{
			StartStaggering(position, Cfg.earthquakeRadius.Value, -1f);
		}
		ResetNextQuake();
	}

	private IEnumerator Co_Clatter(Vector3 position, float delay)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		if (IsShaking())
		{
			yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked()));
		}
		else
		{
			yield return (object)new WaitForSeconds(delay);
		}
		audioHelper.Play(position, "clatter.mp3");
	}

	private static void DamageThings(Vector3 epicenter, float radius, float duration)
	{
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("DamageThings");
		_ = Player.m_localPlayer;
		if (Cfg.maxPieceDamage.Value == 0 && Cfg.maxTreeDamage.Value == 0 && !Cfg.hookedItemsFall.Value && !Cfg.activeItemsMove.Value)
		{
			return;
		}
		Dictionary<WearNTear, float> dictionary = new Dictionary<WearNTear, float>();
		Dictionary<TreeBase, float> dictionary2 = new Dictionary<TreeBase, float>();
		Dictionary<ItemStand, float> dictionary3 = new Dictionary<ItemStand, float>();
		Ship ship = default(Ship);
		Vagon vagon = default(Vagon);
		ItemStand val = default(ItemStand);
		WearNTear val2 = default(WearNTear);
		foreach (WearNTear allInstance in WearNTear.GetAllInstances())
		{
			GameObject gameObject = ((Component)allInstance).gameObject;
			if (gameObject.TryGetComponent<Ship>(ref ship))
			{
				if (Cfg.activeItemsMove.Value && IsShaking())
				{
					((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ShakeShip(ship));
				}
				continue;
			}
			if (gameObject.TryGetComponent<Vagon>(ref vagon))
			{
				if (Cfg.activeItemsMove.Value && IsShaking())
				{
					((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ShakeVagon(vagon));
				}
				continue;
			}
			if (Cfg.hookedItemsFall.Value && gameObject.TryGetComponent<ItemStand>(ref val))
			{
				float value = Vector3.Distance(epicenter, ((Component)val).transform.position);
				if (!dictionary3.ContainsKey(val))
				{
					dictionary3.Add(val, value);
				}
			}
			if (Cfg.maxPieceDamage.Value > 0 && gameObject.TryGetComponent<WearNTear>(ref val2))
			{
				float value2 = Vector3.Distance(epicenter, ((Component)val2).transform.position);
				if (!dictionary.ContainsKey(val2))
				{
					dictionary.Add(val2, value2);
				}
			}
		}
		if (Cfg.maxTreeDamage.Value > 0)
		{
			foreach (TreeBase value4 in treeManager.Values)
			{
				if ((Object)(object)value4 != (Object)null && Random.value > 0.66f)
				{
					float value3 = Vector3.Distance(epicenter, ((Component)value4).transform.position);
					if (!dictionary2.ContainsKey(value4))
					{
						dictionary2.Add(value4, value3);
					}
				}
			}
		}
		float num = Cfg.maxPieceDamage.Value;
		if (TryGetClosestActiveWard(epicenter, 0f, out var distance))
		{
			float num2 = 1f - distance / radius;
			num *= 0.5f * num2;
			Log.Debug("Active ward reduced max damage");
		}
		if (TryGetClosestShieldGenerator(epicenter, 0f, out var distance2))
		{
			float num3 = 1f - distance2 / radius;
			num *= 0.5f * num3;
			Log.Debug("Active shield generator reduced max damage");
		}
		if (dictionary.Count > 0)
		{
			((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DamagePieces(dictionary, radius, num, duration, 1f));
		}
		if (dictionary2.Count > 0)
		{
			((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DamageTrees(dictionary2, epicenter, radius, Cfg.maxTreeDamage.Value, duration, 1f));
		}
		if (dictionary3.Count > 0)
		{
			((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_DropAttachedPieces(dictionary3, radius, duration, 2f));
		}
	}

	private IEnumerator Co_ShakeVagon(Vagon vagon)
	{
		Log.Trace("Co_ShakeVagon");
		object obj;
		if (vagon == null)
		{
			obj = null;
		}
		else
		{
			GameObject gameObject = ((Component)vagon).gameObject;
			obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null);
		}
		Rigidbody rb = (Rigidbody)obj;
		while (IsShaking())
		{
			if ((Object)(object)rb == (Object)null)
			{
				yield break;
			}
			float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle()));
			float num2 = quakeShaker.TimeAdjustedIntensity();
			rb.AddRelativeForce(new Vector3(0f, 0f, num2 * 2f * num), (ForceMode)1);
			yield return null;
		}
		rb.velocity = Vector3.zero;
	}

	private IEnumerator Co_RollLog(TreeLog log)
	{
		Log.Trace("Co_RollLog");
		object obj;
		if (log == null)
		{
			obj = null;
		}
		else
		{
			GameObject gameObject = ((Component)log).gameObject;
			obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null);
		}
		Rigidbody rb = (Rigidbody)obj;
		while (IsShaking())
		{
			if ((Object)(object)rb == (Object)null)
			{
				yield break;
			}
			float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle()));
			float num2 = quakeShaker.TimeAdjustedIntensity();
			rb.AddRelativeTorque(new Vector3(0f, 0f, num2 * 25f * num), (ForceMode)1);
			yield return null;
		}
		rb.angularVelocity = Vector3.zero;
	}

	private IEnumerator Co_ShakeShip(Ship ship)
	{
		Log.Trace("Co_ShakeVagon");
		object obj;
		if (ship == null)
		{
			obj = null;
		}
		else
		{
			GameObject gameObject = ((Component)ship).gameObject;
			obj = ((gameObject != null) ? gameObject.GetComponent<Rigidbody>() : null);
		}
		Rigidbody rb = (Rigidbody)obj;
		while (IsShaking())
		{
			if ((Object)(object)rb == (Object)null)
			{
				yield break;
			}
			float num = Mathf.Sign(Mathf.Sin(quakeShaker.GetCurrentAngle()));
			float num2 = quakeShaker.TimeAdjustedIntensity();
			rb.AddRelativeTorque(new Vector3(0f, 0f, num2 / 4f * num), (ForceMode)1);
			yield return null;
		}
		rb.angularVelocity = Vector3.zero;
	}

	private IEnumerator Co_DropAttachedPieces(Dictionary<ItemStand, float> st, float radius, float duration, float delay)
	{
		Log.Debug("Co_DropAttachedPieces");
		float num;
		if (IsShaking())
		{
			yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked()));
			num = quakeShaker.TimeRemaining();
		}
		else
		{
			yield return (object)new WaitForSeconds(delay);
			num = duration - delay;
		}
		float wait = Mathf.Clamp01(num / 2f / (float)st.Count);
		foreach (KeyValuePair<ItemStand, float> item in st)
		{
			if (Random.value < 0.5f)
			{
				item.Key.DropItem();
			}
			yield return (object)new WaitForSeconds(wait);
		}
	}

	private IEnumerator Co_DamagePieces(Dictionary<WearNTear, float> wnt, float radius, float damage, float duration, float delay)
	{
		Log.Debug("Co_DamagePieces");
		float num;
		if (IsShaking())
		{
			yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked()));
			num = quakeShaker.TimeRemaining();
		}
		else
		{
			yield return (object)new WaitForSeconds(delay);
			num = duration - delay;
		}
		float wait = Mathf.Clamp01(num / 2f / (float)wnt.Count);
		Container val = default(Container);
		foreach (KeyValuePair<WearNTear, float> item in wnt)
		{
			WearNTear key = item.Key;
			float value = item.Value;
			if ((Object)(object)key != (Object)null && !((Component)key).gameObject.TryGetComponent<Container>(ref val))
			{
				float num2 = damage * (1f - value / radius);
				float maxSupport = key.GetMaxSupport();
				float num3 = 1f - key.m_support * 0.9f / maxSupport;
				DamagePiece(key, num2 * num3);
			}
			yield return (object)new WaitForSeconds(wait);
		}
	}

	private IEnumerator Co_DamageTrees(Dictionary<TreeBase, float> tb, Vector3 epicenter, float radius, float damage, float duration, float delay)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("Co_DamageTrees");
		float num;
		if (IsShaking())
		{
			yield return (object)new WaitUntil((Func<bool>)(() => quakeShaker.HasPeaked()));
			num = quakeShaker.TimeRemaining();
		}
		else
		{
			yield return (object)new WaitForSeconds(delay);
			num = duration - delay;
		}
		float wait = Mathf.Clamp01(num / 2f / (float)tb.Count);
		foreach (KeyValuePair<TreeBase, float> item in tb)
		{
			TreeBase key = item.Key;
			float value = item.Value;
			float distanceAdjDamage = damage * (1f - value / radius);
			DamageTree(key, epicenter, distanceAdjDamage);
			yield return (object)new WaitForSeconds(wait);
		}
	}

	private static void DamagePiece(WearNTear wnt, float distanceAdjDamage)
	{
		if ((Object)(object)wnt == (Object)null || (Object)(object)wnt.m_nview == (Object)null || !wnt.m_nview.IsValid() || !wnt.m_nview.IsOwner())
		{
			return;
		}
		float @float = wnt.m_nview.GetZDO().GetFloat(ZDOVars.s_health, wnt.m_health);
		float num = RandomToMax(distanceAdjDamage, 0.75f);
		float num2 = @float - num;
		if (num2 <= 0f && Cfg.allowFullDestruction.Value)
		{
			wnt.Destroy((HitData)null);
			return;
		}
		num2 = Mathf.Clamp(num2, 1f, num2);
		if (@float > 1f)
		{
			if ((float)Cfg.displacementChance.Value > 0f)
			{
				Displace(((Component)wnt).transform);
			}
			wnt.m_nview.GetZDO().Set(ZDOVars.s_health, num2);
			wnt.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_HealthChanged", new object[1] { num2 });
			wnt.SetHealthVisual(num2 / wnt.m_health, true);
		}
	}

	private static void DamageTree(TreeBase treeBase, Vector3 epicenter, float distanceAdjDamage)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)treeBase == (Object)null) && treeBase.m_nview.IsValid())
		{
			treeBase.m_nview.m_zdo.Owned = true;
			treeBase.m_nview.m_zdo.Owner = true;
			HitData val = new HitData();
			val.m_attacker = ZDOID.None;
			val.m_itemWorldLevel = 100;
			val.m_toolTier = 100;
			val.m_damage.m_chop = RandomToMax(distanceAdjDamage, 0.75f);
			val.m_dir = epicenter - ((Component)treeBase).transform.position;
			val.m_dir.y = 0f;
			val.m_dir = Vector3.Normalize(val.m_dir);
			treeBase.Damage(val);
		}
	}

	private static void StartStaggering(Vector3 epicenter, float radius, float delay = 0f)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("StartStaggering");
		if (Cfg.charactersStagger.Value)
		{
			((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_StaggerController(epicenter, radius, delay));
		}
	}

	private IEnumerator Co_StaggerController(Vector3 epicenter, float radius, float delay)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (!IsShaking() || quakeShaker.TimeRemaining() < quakeShaker.Duration * 0.2f)
		{
			yield break;
		}
		if (delay < 0f)
		{
			yield return (object)new WaitUntil((Func<bool>)(() => halfCracked));
		}
		else if (delay > 0f)
		{
			yield return (object)new WaitForSeconds(delay);
		}
		List<Character> characters = new List<Character>();
		Utils.GetCharactersInRangeXZ(epicenter, radius, characters);
		Object.Instantiate<GameObject>(cracking_sfx, epicenter, Quaternion.identity);
		bool randomize = false;
		float randomChance = 0.5f;
		do
		{
			foreach (Character item in characters)
			{
				if ((!randomize || Random.value < randomChance) && (Object)(object)item != (Object)null && OkToStagger(item))
				{
					item.Stagger(((Component)item).transform.position);
				}
				yield return null;
			}
			randomize = true;
			randomChance = Mathf.Clamp01(randomChance - 0.1f);
			radius *= 0.8f;
			yield return (object)new WaitForSeconds(2f);
		}
		while (quakeShaker.InPeakWindow());
	}

	private static void PseudoApplyOperation(ZNetView m_nview, Vector3 epicenter, Settings tos)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		Log.Trace("PseudoApplyOperation");
		ZPackage val = new ZPackage();
		val.Write(epicenter);
		tos.Serialize(val);
		m_nview.InvokeRPC("ApplyOperation", new object[1] { val });
	}

	private static bool FissureExists(Heightmap hm, Vector3 point)
	{
		//IL_0001: 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)
		float num = default(float);
		hm.GetWorldHeight(point, ref num);
		float num2 = default(float);
		hm.GetWorldBaseHeight(point, ref num2);
		return num < num2 - Cfg.fissureMaxDepth.Value * 0.9f;
	}

	private static int GetSeedFromHeightmap(Heightmap hm)
	{
		//IL_0006: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		int num = Convert.ToInt32(Mathf.Clamp(Mathf.Abs(((Component)hm).transform.position.x * 3f + ((Component)hm).transform.position.z * 2f + ((Component)hm).transform.position.y), 0f, 2.1474836E+09f));
		Log.Debug($"Seed from heightmap {num}");
		return num;
	}

	private static Vector2Int[] GetActionPoints(Vector2Int curXY, Vector3 worldPos)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: 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)
		int x = ((Vector2Int)(ref curXY)).x;
		int y = ((Vector2Int)(ref curXY)).y;
		List<Vector2Int> list = new List<Vector2Int> { curXY };
		if (Vector2Int.op_Implicit(lastFissureXY) != Vector2.zero)
		{
			if (((Vector2Int)(ref lastFissureXY)).x == ((Vector2Int)(ref curXY)).x && ((Vector2Int)(ref lastFissureXY)).y == ((Vector2Int)(ref curXY)).y)
			{
				if (Mathf.Abs(worldPos.x - lastWorldPos.x) > Mathf.Abs(worldPos.y - lastWorldPos.y))
				{
					x = ((worldPos.x > lastWorldPos.x) ? (x + 1) : (x - 1));
					list.Add(new Vector2Int(x, ((Vector2Int)(ref curXY)).y));
					y = ((worldPos.y > lastWorldPos.y) ? (y + 1) : (y - 1));
					list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, y));
				}
			}
			else if (((Vector2Int)(ref lastFissureXY)).x != ((Vector2Int)(ref curXY)).x && ((Vector2Int)(ref lastFissureXY)).y != ((Vector2Int)(ref curXY)).y)
			{
				list.Add(new Vector2Int(((Vector2Int)(ref lastFissureXY)).x, ((Vector2Int)(ref curXY)).y));
				list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, ((Vector2Int)(ref lastFissureXY)).y));
			}
			else if (((Vector2Int)(ref lastFissureXY)).x == ((Vector2Int)(ref curXY)).x)
			{
				x = ((worldPos.x > lastWorldPos.x) ? (x + 1) : (x - 1));
				list.Add(new Vector2Int(x, ((Vector2Int)(ref curXY)).y));
			}
			else if (((Vector2Int)(ref lastFissureXY)).y == ((Vector2Int)(ref curXY)).y)
			{
				y = ((worldPos.y > lastWorldPos.y) ? (y + 1) : (y - 1));
				list.Add(new Vector2Int(((Vector2Int)(ref curXY)).x, y));
			}
		}
		return list.ToArray();
	}

	private static float RestrictedRandomDirection(CrossPlatformRandom random)
	{
		float num = random.Range(5f, 40f);
		return (float)(int)random.Range(0, 9) * 45f + num;
	}

	public static float GetDogLegDirection(float angle, CrossPlatformRandom random)
	{
		return (angle + 180f + random.Range(15f, 35f)) % 360f;
	}

	private static bool CreateFissure(Heightmap hm)
	{
		//IL_0058: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("CreateFissure");
		bool result = true;
		float num = Cfg.fissureMaxDepth.Value;
		CrossPlatformRandom crossPlatformRandom = new CrossPlatformRandom(GetSeedFromHeightmap(hm));
		if (crossPlatformRandom.value * 100f > Cfg.faultChance.Value)
		{
			Log.Debug("No fault line in current zone");
			return result;
		}
		if (FissureExists(hm, ((Bounds)(ref hm.m_bounds)).center))
		{
			num *= Cfg.fissureDeepenPct.Value;
			Log.Debug("Fissure already exists. Using percentage of max depth.");
		}
		if (fissure_vfx == null)
		{
			fissure_vfx = Utils.GetPrefab("vfx_Place_mud_road");
		}
		if (cracking_sfx == null)
		{
			cracking_sfx = Utils.GetPrefab("sfx_stonegolem_attack_hit");
		}
		float num2 = RestrictedRandomDirection(crossPlatformRandom);
		float num3 = GetDogLegDirection(num2, crossPlatformRandom);
		Vector3 center = ((Bounds)(ref hm.m_bounds)).center;
		int num4 = default(int);
		int num5 = default(int);
		hm.WorldToVertex(center, ref num4, ref num5);
		float num6 = Mathf.Min((float)hm.m_width * crossPlatformRandom.Range(0.7f, 0.9f), (float)Cfg.earthquakeRadius.Value);
		float num7 = fissureSpacing;
		int num8 = Mathf.CeilToInt(num6 / 4f / num7);
		Vector3 val = center;
		Vector3 val2 = center;
		float num9 = 0f;
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		list.Add(center);
		int num10 = 0;
		int num11 = 1;
		int num12 = 1;
		while (num9 < num6)
		{
			float num13 = num7;
			float num14 = num7;
			Vector3 val3 = val + Quaternion.Euler(0f, num3, 0f) * Vector3.forward * num13;
			Vector3 val4 = val2 + Quaternion.Euler(0f, num2, 0f) * Vector3.forward * num14;
			num9 += num13 + num14;
			num11 += 2;
			list.Add(val3);
			list2.Add(val4);
			val = val3;
			val2 = val4;
			if (++num10 % num8 == 0)
			{
				num3 += crossPlatformRandom.Range(20, 30) * (float)(-num12);
				num2 += crossPlatformRandom.Range(20, 30) * (float)num12;
				num12 = -num12;
			}
		}
		list2.Reverse();
		list2.AddRange(list);
		Vector3[] tpa = list2.ToArray();
		((MonoBehaviour)_modInstance).StartCoroutine(_modInstance.Co_ModifyTerrain(tpa, center, fissureRadius, num, num11, 2f));
		return result;
	}

	public static float GraduatedDepth(int nbrSegments, int seg, float depth)
	{
		float num = (float)nbrSegments / 2f;
		float num2 = Mathf.Abs((float)seg - num) / num;
		return depth * (1f - num2);
	}

	private IEnumerator Co_ModifyTerrain(Vector3[] tpa, Vector3 epicenter, float radius, float depth, int nbrSegments, float delay)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug("Co_ModifyTerrain");
		if (IsShaking())
		{
			yield return