Decompiled source of GC Server v1.8.1

patchers\GC_ModSchalter_Server.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_ModSchalter")]
[assembly: AssemblyTitle("GC_ModSchalter_Server")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Patcher
{
	public static class ModSchalter
	{
		public const string KernGuid = "gorduan.gc.kern";

		private static readonly string[] OldPackages = new string[3] { "gorduan.gc_server", "gorduan.gc_client", "gorduan.valheimplusplus" };

		public const string DataInstalled = "GC.ModSchalter.Installed";

		public const string DataBest = "GC.ModSchalter.Best";

		public const string DataAll = "GC.ModSchalter.All";

		public const string DataSkipped = "GC.ModSchalter.Skipped";

		public const string DataProtected = "GC.ModSchalter.Protected";

		public const string DataFile = "GC.ModSchalter.File";

		private static readonly ManualLogSource Log = Logger.CreateLogSource("GC_ModSchalter");

		public static IEnumerable<string> TargetDLLs { get; } = Array.Empty<string>();

		public static string ListFile => Path.Combine(Path.Combine(Paths.ConfigPath, "GC_Kern"), "aus.txt");

		private static Version Own => typeof(ModSchalter).Assembly.GetName().Version;

		public static void Patch(AssemblyDefinition assembly)
		{
		}

		public static void Initialize()
		{
			AppDomain currentDomain = AppDomain.CurrentDomain;
			if (!(currentDomain.GetData("GC.ModSchalter.Best") is Version version) || Own > version)
			{
				currentDomain.SetData("GC.ModSchalter.Best", Own);
			}
		}

		public static void Finish()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			AppDomain currentDomain = AppDomain.CurrentDomain;
			object data = currentDomain.GetData("GC.ModSchalter.Installed");
			bool flag = default(bool);
			int num;
			if (data is bool)
			{
				flag = (bool)data;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0 || (currentDomain.GetData("GC.ModSchalter.Best") is Version version && Own < version))
			{
				return;
			}
			currentDomain.SetData("GC.ModSchalter.Installed", true);
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(TypeLoader), "FindPluginTypes", (Type[])null, (Type[])null).MakeGenericMethod(typeof(PluginInfo));
				new Harmony("gorduan.gc.modschalter").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ModSchalter), "FindPluginTypesPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				currentDomain.SetData("GC.ModSchalter.File", ListFile);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Konnte sich nicht in BepInEx einhängen, alle Mods laden: {arg}");
			}
		}

		private static void FindPluginTypesPostfix(string cacheName, Dictionary<string, List<PluginInfo>> __result)
		{
			if (cacheName != "chainloader" || __result == null)
			{
				return;
			}
			try
			{
				List<PluginInfo> list = __result.Values.SelectMany((List<PluginInfo> result) => result).ToList();
				AppDomain.CurrentDomain.SetData("GC.ModSchalter.All", list);
				HashSet<string> hashSet = ReadList(ListFile);
				if (hashSet.Count == 0)
				{
					return;
				}
				if (!list.Any((PluginInfo info) => string.Equals(info.Metadata.GUID, "gorduan.gc.kern", StringComparison.OrdinalIgnoreCase)))
				{
					Log.LogWarning((object)"GC_Kern fehlt: aus.txt gilt nicht, alle Mods laden.");
					return;
				}
				if (list.Any((PluginInfo info) => OldPackages.Contains<string>(info.Metadata.GUID, StringComparer.OrdinalIgnoreCase)))
				{
					Log.LogWarning((object)"Ein altes GC-Sammelpaket liegt noch im Ordner, GC_Kern startet dann nicht: aus.txt gilt nicht, alle Mods laden.");
					return;
				}
				HashSet<string> hashSet2 = Protected(list);
				List<PluginInfo> list2 = new List<PluginInfo>();
				PropertyInfo propertyInfo = AccessTools.Property(typeof(PluginInfo), "Location");
				foreach (KeyValuePair<string, List<PluginInfo>> item in __result.ToList())
				{
					foreach (PluginInfo item2 in item.Value.ToList())
					{
						if (hashSet.Contains(item2.Metadata.GUID) && !hashSet2.Contains(item2.Metadata.GUID))
						{
							propertyInfo?.SetValue(item2, item.Key, null);
							item.Value.Remove(item2);
							list2.Add(item2);
							Log.LogMessage((object)$"Im Menü GC Option ausgeschaltet, wird nicht geladen: [{item2}]");
						}
					}
					if (item.Value.Count == 0)
					{
						__result.Remove(item.Key);
					}
				}
				AppDomain.CurrentDomain.SetData("GC.ModSchalter.Skipped", list2);
				AppDomain.CurrentDomain.SetData("GC.ModSchalter.Protected", hashSet2.ToArray());
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Ausgeschaltete Mods nicht gefiltert, alle Mods laden: {arg}");
			}
		}

		private static HashSet<string> Protected(List<PluginInfo> all)
		{
			//IL_0095: 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)
			Dictionary<string, PluginInfo> dictionary = new Dictionary<string, PluginInfo>(StringComparer.OrdinalIgnoreCase);
			foreach (PluginInfo item in all)
			{
				dictionary[item.Metadata.GUID] = item;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "gorduan.gc.kern" };
			Queue<string> queue = new Queue<string>(hashSet);
			while (queue.Count > 0)
			{
				if (!dictionary.TryGetValue(queue.Dequeue(), out var value))
				{
					continue;
				}
				foreach (BepInDependency dependency in value.Dependencies)
				{
					if ((dependency.Flags & 1) != 0 && hashSet.Add(dependency.DependencyGUID))
					{
						queue.Enqueue(dependency.DependencyGUID);
					}
				}
			}
			return hashSet;
		}

		public static HashSet<string> ReadList(string file)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (!File.Exists(file))
			{
				return hashSet;
			}
			string[] array = File.ReadAllLines(file);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0 && !text.StartsWith("#", StringComparison.Ordinal))
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Felder.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Client;
using GC.Client.Fields;
using GC.Server;
using GC.Server.Fields;
using GC.Shared;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Felder")]
[assembly: AssemblyTitle("GC_Felder")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.Fields
{
	public enum Removers
	{
		Everyone,
		CreatorOrAdmin,
		CreatorGuildLeadersOrAdmin,
		AdminOnly
	}
	internal static class Plugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<Removers> RemoveBy;

		internal static ConfigEntry<int> MaxPoints;

		internal static ConfigEntry<float> MaxEdge;

		internal static ConfigEntry<float> Reach;

		internal static ConfigEntry<float> Interval;

		internal static ConfigEntry<float> SpacingBush;

		internal static ConfigEntry<float> SpacingMushroom;

		internal static ConfigEntry<float> SpacingOther;

		internal static void Init(ConfigFile Config)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "11 - Fields", "Enabled", true, "Felder mit dem Kultivator markieren und automatisch in Reihen bepflanzen (Zeichnen und Pflanzen in GC_Client, wird vom Server vorgegeben).", (AcceptableValueBase)null);
			RemoveBy = Gc.BindSynced<Removers>(Config, "11 - Fields", "RemoveBy", Removers.Everyone, "Wer ein Feld aufheben darf: Everyone (alle), CreatorOrAdmin (Ersteller und Admins), CreatorGuildLeadersOrAdmin (Ersteller, Leiter und Co-Leiter seiner Gilde, Admins; ohne Gilden-Mod wie CreatorOrAdmin), AdminOnly (nur Admins). Die Pflanzen bleiben immer stehen.", (AcceptableValueBase)null);
			MaxPoints = Gc.BindSynced<int>(Config, "11 - Fields", "MaxPoints", 32, "Höchstzahl Eckpunkte je Feld, 0 = unbegrenzt.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000));
			MaxEdge = Gc.BindSynced<float>(Config, "11 - Fields", "MaxEdgeLength", 50f, "Höchstlänge einer Feldkante in Metern, 0 = unbegrenzt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f));
			Reach = Gc.BindSynced<float>(Config, "11 - Fields", "Reach", 10f, "So weit vom Spieler werden Plätze im Feld bepflanzt (Meter). Man kann sich dabei bewegen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f));
			Interval = Gc.BindSynced<float>(Config, "11 - Fields", "PlantInterval", 0.5f, "Sekunden zwischen zwei Pflanzen beim Halten von E (Valheim selbst braucht mindestens 0,4 s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f));
			SpacingBush = Gc.BindSynced<float>(Config, "11 - Fields", "SpacingBush", 1.5f, "Abstand für Sträucher ohne eigene Wachstumsregel (z. B. Beerensträucher aus PlantEverything), in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f));
			SpacingMushroom = Gc.BindSynced<float>(Config, "11 - Fields", "SpacingMushroom", 0.5f, "Abstand für Pilze ohne eigene Wachstumsregel, in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f));
			SpacingOther = Gc.BindSynced<float>(Config, "11 - Fields", "SpacingOther", 1f, "Abstand für alles andere ohne eigene Wachstumsregel (Blumen, Disteln usw.), in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f));
			GcFields.Publish(new Dictionary<string, Func<object>>
			{
				["enabled"] = () => Enabled.Value,
				["removeBy"] = () => (int)RemoveBy.Value,
				["maxPoints"] = () => MaxPoints.Value,
				["maxEdge"] = () => MaxEdge.Value,
				["reach"] = () => Reach.Value,
				["interval"] = () => Interval.Value,
				["spacingBush"] = () => SpacingBush.Value,
				["spacingMushroom"] = () => SpacingMushroom.Value,
				["spacingOther"] = () => SpacingOther.Value
			});
			PrefabManager.OnVanillaPrefabsAvailable += CreatePrefab;
		}

		private static void CreatePrefab()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreatePrefab;
			GameObject val = PrefabManager.Instance.CreateEmptyPrefab("GC_Field", true);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Felder: Welt-Objekt GC_Field konnte nicht angelegt werden.");
				return;
			}
			Component[] components = val.GetComponents<Component>();
			foreach (Component val2 in components)
			{
				if (val2 is Collider || val2 is Renderer || val2 is MeshFilter)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			ZNetView component = val.GetComponent<ZNetView>();
			component.m_persistent = true;
			component.m_distant = true;
			PrefabManager.Instance.AddPrefab(new CustomPrefab(val, false));
			Log.LogInfo((object)"Felder: Welt-Objekt GC_Field angelegt.");
		}
	}
}
namespace GC.Mods.Felder
{
	[BepInPlugin("gorduan.gc.felder", "GC_Felder", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ClientPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ClientPlugin.Module = Module;
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.felder");
			GC.Client.Fields.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			GC.Server.Fields.Plugin.Init(((BaseUnityPlugin)this).Config);
			Module.TakeOverOldSettings();
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("fields", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("fields_remove", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.RemoveBy, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_points", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.MaxPoints, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_edge", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.MaxEdge, 5.0, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_reach", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.Reach, 1.0, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_interval", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.Interval, 0.1, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_bush", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.SpacingBush, 0.1, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_mushroom", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.SpacingMushroom, 0.1, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_other", (ConfigEntryBase)(object)GC.Server.Fields.Plugin.SpacingOther, 0.1, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gccm_" + key, Array.Empty<object>())), "gck_mod_felder_anzeige").Main("fields", (ConfigEntryBase)(object)GC.Client.Fields.Plugin.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("fields_color", (ConfigEntryBase)(object)GC.Client.Fields.Plugin.Tint, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_fill", (ConfigEntryBase)(object)GC.Client.Fields.Plugin.FillOpacity, 5.0, " %", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("fields_line", (ConfigEntryBase)(object)GC.Client.Fields.Plugin.LineOpacity, 5.0, " %", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}

		private void Update()
		{
			if (!Gc.IsHeadless)
			{
				Module.Guard("Felder", (Action)GC.Client.Fields.Plugin.Update);
			}
		}
	}
	internal static class GcMod
	{
		public const string Id = "felder";

		public const string Guid = "gorduan.gc.felder";

		public const string Name = "GC_Felder";

		public const string Version = "1.8.1";

		public const int Stufe = 3;

		public static GcModInfo Info => new GcModInfo
		{
			Id = "felder",
			Guid = "gorduan.gc.felder",
			Name = "GC_Felder",
			Version = "1.8.1",
			Stufe = 3,
			Seite = (GcSeite)1,
			Braucht = Array.Empty<string>(),
			Partner = Array.Empty<string>(),
			Fremd = Array.Empty<string>(),
			AlteConfig = "gorduan.gc_client.cfg;gorduan.gc_server.cfg",
			Ausgleich = 0f
		};
	}
}
namespace GC.Client
{
	internal static class ClientPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Client.Fields
{
	internal sealed class Spec
	{
		public Piece Piece;

		public Plant? Plant;

		public float Radius;

		public float Body;

		public float Step;
	}
	internal struct Neighbour
	{
		public Vector3 Position;

		public float Radius;

		public float Body;
	}
	internal static class Planting
	{
		private enum Kind : byte
		{
			None,
			Plant,
			Pickable
		}

		private struct PrefabInfo
		{
			public Kind Kind;

			public float Radius;

			public float Body;
		}

		private const float Margin = 0.05f;

		private const float Slack = 0.02f;

		private const string PlantEasilyGuid = "advize.PlantEasily";

		private static readonly Dictionary<string, Spec> Specs = new Dictionary<string, Spec>();

		private static readonly Dictionary<string, float> Bodies = new Dictionary<string, float>();

		private static readonly Dictionary<int, PrefabInfo> Prefabs = new Dictionary<int, PrefabInfo>();

		private static Dictionary<string, float>? grownRadius;

		private static float cachesUntil;

		private static readonly List<Neighbour> Neighbours = new List<Neighbour>();

		private static readonly Dictionary<long, float> Failed = new Dictionary<long, float>();

		private static readonly List<long> Expired = new List<long>();

		private static readonly List<(Vector3 Position, Spec Spec, float Until)> Recent = new List<(Vector3, Spec, float)>();

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

		private static int roofMask;

		private static int spaceMask;

		private static bool inGhost;

		internal static bool Redirected;

		private static bool blocking;

		private static Vector3 target;

		private static PlacementStatus captured;

		private static Vector3 capturedPosition;

		private static bool lastValid;

		private static Vector3? slot;

		private static float searchUntil;

		private static FieldView? slotField;

		private static Spec? slotSpec;

		private static bool holding;

		private static bool noSeeds;

		private static float nextAuto;

		private static float autoClickUntil;

		private static float nextNoSlot;

		private static bool warnedPlantEasily;

		private static float Reach => GcFields.Get<float>("reach", 10f);

		internal static bool PlantEasily => Chainloader.PluginInfos.ContainsKey("advize.PlantEasily");

		internal static void ResetCaches()
		{
			Specs.Clear();
			Bodies.Clear();
			Prefabs.Clear();
			grownRadius = null;
			Recent.Clear();
			Failed.Clear();
			slot = null;
			slotField = null;
			slotSpec = null;
		}

		internal static bool IsPlantable(Piece? piece)
		{
			if ((Object)(object)piece != (Object)null && !Plugin.IsMarker(piece) && (Object)(object)((Component)piece).GetComponent<TerrainOp>() == (Object)null)
			{
				if (!((Object)(object)((Component)piece).GetComponent<Plant>() != (Object)null))
				{
					return (Object)(object)((Component)piece).GetComponent<Pickable>() != (Object)null;
				}
				return true;
			}
			return false;
		}

		private static void RefreshCaches()
		{
			if (!(Time.time < cachesUntil))
			{
				cachesUntil = Time.time + 30f;
				Specs.Clear();
				Prefabs.Clear();
				grownRadius = null;
			}
		}

		private static Spec SpecOf(Piece piece)
		{
			string name = ((Object)((Component)piece).gameObject).name;
			if (Specs.TryGetValue(name, out Spec value) && (Object)(object)value.Piece == (Object)(object)piece)
			{
				return value;
			}
			Plant component = ((Component)piece).GetComponent<Plant>();
			float num = BodyOf(name, ((Component)piece).gameObject);
			float num2 = (((Object)(object)component != (Object)null) ? component.m_growRadius : Mathf.Max(0.05f, Spacing(name) - num));
			value = new Spec
			{
				Piece = piece,
				Plant = component,
				Radius = num2,
				Body = num,
				Step = num2 + num + 0.05f + 0.02f
			};
			Specs[name] = value;
			return value;
		}

		private static float Spacing(string name)
		{
			string text = name.ToLowerInvariant();
			if (text.Contains("bush"))
			{
				return GcFields.Get<float>("spacingBush", 1.5f);
			}
			if (text.Contains("mushroom"))
			{
				return GcFields.Get<float>("spacingMushroom", 0.5f);
			}
			return GcFields.Get<float>("spacingOther", 1f);
		}

		private static float BodyOf(string name, GameObject? instance)
		{
			if (Bodies.TryGetValue(name, out var value))
			{
				return value;
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null);
			GameObject val2 = (GameObject)(((Object)(object)val != (Object)null) ? ((object)val) : ((object)instance));
			value = (((Object)(object)val2 != (Object)null) ? ColliderRadius(val2) : 0.2f);
			Plant val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Plant>() : null);
			if ((Object)(object)val3 != (Object)null && val3.m_grownPrefabs != null)
			{
				GameObject[] grownPrefabs = val3.m_grownPrefabs;
				foreach (GameObject val4 in grownPrefabs)
				{
					if ((Object)(object)val4 != (Object)null)
					{
						value = Mathf.Max(value, ColliderRadius(val4));
					}
				}
			}
			value = Mathf.Clamp(value, 0.05f, 1.5f);
			Bodies[name] = value;
			return value;
		}

		private static float ColliderRadius(GameObject go)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			Transform transform = go.transform;
			Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (val.isTrigger)
				{
					continue;
				}
				Vector3 lossyScale = ((Component)val).transform.lossyScale;
				float num2 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z));
				Vector3 val2 = transform.InverseTransformPoint(((Component)val).transform.position);
				Vector2 val3 = new Vector2(val2.x, val2.z);
				float magnitude = ((Vector2)(ref val3)).magnitude;
				Collider val4 = val;
				CapsuleCollider val5 = (CapsuleCollider)(object)((val4 is CapsuleCollider) ? val4 : null);
				float num4;
				if (val5 == null)
				{
					SphereCollider val6 = (SphereCollider)(object)((val4 is SphereCollider) ? val4 : null);
					if (val6 == null)
					{
						BoxCollider val7 = (BoxCollider)(object)((val4 is BoxCollider) ? val4 : null);
						if (val7 == null)
						{
							MeshCollider val8 = (MeshCollider)(object)((val4 is MeshCollider) ? val4 : null);
							if (val8 != null && (Object)(object)val8.sharedMesh != (Object)null)
							{
								Bounds bounds = val8.sharedMesh.bounds;
								float num3 = ((Bounds)(ref bounds)).extents.x * Mathf.Abs(lossyScale.x);
								bounds = val8.sharedMesh.bounds;
								num4 = Mathf.Max(num3, ((Bounds)(ref bounds)).extents.z * Mathf.Abs(lossyScale.z));
							}
							else
							{
								num4 = 0f;
							}
						}
						else
						{
							float num5 = 0.5f * Mathf.Max(val7.size.x * Mathf.Abs(lossyScale.x), val7.size.z * Mathf.Abs(lossyScale.z));
							val3 = new Vector2(val7.center.x, val7.center.z);
							num4 = num5 + ((Vector2)(ref val3)).magnitude * num2;
						}
					}
					else
					{
						float num6 = val6.radius * num2;
						val3 = new Vector2(val6.center.x, val6.center.z);
						num4 = num6 + ((Vector2)(ref val3)).magnitude * num2;
					}
				}
				else
				{
					float num7 = val5.radius * num2;
					val3 = new Vector2(val5.center.x, val5.center.z);
					num4 = num7 + ((Vector2)(ref val3)).magnitude * num2;
				}
				float num8 = num4;
				num = Mathf.Max(num, num8 + magnitude);
			}
			return num;
		}

		private static float GrownRadius(string name)
		{
			if (grownRadius == null)
			{
				grownRadius = new Dictionary<string, float>();
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
					{
						Plant val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Plant>() : null);
						if (val?.m_grownPrefabs == null)
						{
							continue;
						}
						GameObject[] grownPrefabs = val.m_grownPrefabs;
						foreach (GameObject val2 in grownPrefabs)
						{
							if ((Object)(object)val2 != (Object)null && (!grownRadius.TryGetValue(((Object)val2).name, out var value) || val.m_growRadius > value))
							{
								grownRadius[((Object)val2).name] = val.m_growRadius;
							}
						}
					}
				}
			}
			if (!grownRadius.TryGetValue(name, out var value2))
			{
				return -1f;
			}
			return value2;
		}

		private static PrefabInfo InfoOf(int hash)
		{
			if (Prefabs.TryGetValue(hash, out var value))
			{
				return value;
			}
			value = new PrefabInfo
			{
				Kind = Kind.None
			};
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(hash) : null);
			if ((Object)(object)val != (Object)null)
			{
				Plant component = val.GetComponent<Plant>();
				if ((Object)(object)component != (Object)null)
				{
					value = new PrefabInfo
					{
						Kind = Kind.Plant,
						Radius = component.m_growRadius,
						Body = BodyOf(((Object)val).name, val)
					};
				}
				else if ((Object)(object)val.GetComponent<Pickable>() != (Object)null)
				{
					float num = BodyOf(((Object)val).name, val);
					float num2 = GrownRadius(((Object)val).name);
					value = new PrefabInfo
					{
						Kind = Kind.Pickable,
						Radius = ((num2 >= 0f) ? num2 : Mathf.Max(0.05f, Spacing(((Object)val).name) - num)),
						Body = num
					};
				}
			}
			Prefabs[hash] = value;
			return value;
		}

		private static void CollectNeighbours(Vector3 around, float range)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			Neighbours.Clear();
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			float num = range * range;
			foreach (KeyValuePair<ZDO, ZNetView> instance in ZNetScene.instance.m_instances)
			{
				ZDO key = instance.Key;
				Vector3 position = key.GetPosition();
				float num2 = position.x - around.x;
				float num3 = position.z - around.z;
				if (!(num2 * num2 + num3 * num3 > num))
				{
					PrefabInfo prefabInfo = InfoOf(key.GetPrefab());
					if (prefabInfo.Kind != Kind.None)
					{
						Neighbours.Add(new Neighbour
						{
							Position = position,
							Radius = prefabInfo.Radius,
							Body = prefabInfo.Body
						});
					}
				}
			}
			for (int num4 = Recent.Count - 1; num4 >= 0; num4--)
			{
				if (Time.time > Recent[num4].Until)
				{
					Recent.RemoveAt(num4);
				}
				else
				{
					Neighbours.Add(new Neighbour
					{
						Position = Recent[num4].Position,
						Radius = Recent[num4].Spec.Radius,
						Body = Recent[num4].Spec.Body
					});
				}
			}
		}

		private static bool PairOk(Vector3 point, Spec spec)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			foreach (Neighbour neighbour in Neighbours)
			{
				float num = Mathf.Max(spec.Radius + neighbour.Body, neighbour.Radius + spec.Body) + 0.05f;
				float num2 = neighbour.Position.x - point.x;
				float num3 = neighbour.Position.z - point.z;
				if (num2 * num2 + num3 * num3 < num * num)
				{
					return false;
				}
			}
			return true;
		}

		private static bool Grows(Vector3 point, Spec spec)
		{
			//IL_0021: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Invalid comparison between Unknown and I4
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0110: 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_00c4: Invalid comparison between Unknown and I4
			if ((Object)(object)ZoneSystem.instance != (Object)null && point.y < ZoneSystem.instance.m_waterLevel)
			{
				return false;
			}
			Heightmap val = Heightmap.FindHeightmap(point);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Biome biome = val.GetBiome(point, 0.02f, false);
			if ((int)spec.Piece.m_onlyInBiome != 0 && (biome & spec.Piece.m_onlyInBiome) == 0)
			{
				return false;
			}
			Plant plant = spec.Plant;
			if ((Object)(object)plant != (Object)null)
			{
				if ((biome & plant.m_biome) == 0 || (plant.m_needCultivatedGround && !val.IsCultivated(point)) || plant.m_attachDistance > 0f)
				{
					return false;
				}
				bool flag = ShieldGenerator.IsInsideShield(point);
				if ((!plant.m_tolerateHeat && (int)biome == 32 && !flag) || (!plant.m_tolerateCold && ((int)biome == 64 || (int)biome == 4) && !flag))
				{
					return false;
				}
				if (roofMask == 0)
				{
					roofMask = LayerMask.GetMask(new string[3] { "Default", "static_solid", "piece" });
				}
				if (Physics.Raycast(point + Vector3.up * 0.1f, Vector3.up, 100f, roofMask))
				{
					return false;
				}
			}
			if (spec.Piece.m_cultivatedGroundOnly && !val.IsCultivated(point))
			{
				return false;
			}
			if (spaceMask == 0)
			{
				spaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });
			}
			int num = Physics.OverlapSphereNonAlloc(point, spec.Radius + 0.02f, Hits, spaceMask);
			for (int i = 0; i < num; i++)
			{
				Collider val2 = Hits[i];
				if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).GetComponentInParent<Plant>() == (Object)null && (Object)(object)((Component)val2).GetComponentInParent<Pickable>() == (Object)null)
				{
					return false;
				}
			}
			return true;
		}

		private static long Key(Vector3 point)
		{
			//IL_0000: 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)
			return ((long)Mathf.RoundToInt(point.x * 10f) << 32) ^ (uint)Mathf.RoundToInt(point.z * 10f);
		}

		private static bool IsFailed(Vector3 point)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Failed.TryGetValue(Key(point), out var value))
			{
				return Time.time < value;
			}
			return false;
		}

		private static Vector3? Search(Player player, Field field, Spec spec)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)player).transform.position;
			float reach = Reach;
			CollectNeighbours(position, reach + 4f);
			float step = spec.Step;
			float num = step * 0.8660254f;
			float num2 = Mathf.Min(spec.Body, 0.25f) + 0.05f;
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			float num5 = float.MaxValue;
			float num6 = float.MinValue;
			foreach (Vector3 point in field.Points)
			{
				Vector3 val = point - field.Origin;
				float num7 = val.x * field.Along.x + val.z * field.Along.z;
				float num8 = val.x * field.Inward.x + val.z * field.Inward.z;
				num3 = Mathf.Min(num3, num7);
				num4 = Mathf.Max(num4, num7);
				num5 = Mathf.Min(num5, num8);
				num6 = Mathf.Max(num6, num8);
			}
			Vector3 val2 = position - field.Origin;
			float num9 = val2.x * field.Along.x + val2.z * field.Along.z;
			float num10 = val2.x * field.Inward.x + val2.z * field.Inward.z;
			num3 = Mathf.Max(num3, num9 - reach);
			num4 = Mathf.Min(num4, num9 + reach);
			num5 = Mathf.Max(num5, num10 - reach);
			num6 = Mathf.Min(num6, num10 + reach);
			if (num3 > num4 || num5 > num6)
			{
				return null;
			}
			int num11 = Mathf.FloorToInt((num5 - num2) / num);
			int num12 = Mathf.CeilToInt((num6 - num2) / num);
			for (int i = num11; i <= num12; i++)
			{
				float num13 = num2 + (float)i * num;
				float num14 = (((i & 1) == 1) ? (step * 0.5f) : 0f);
				int num15 = Mathf.FloorToInt((num3 - num14) / step);
				int num16 = Mathf.CeilToInt((num4 - num14) / step);
				for (int j = num15; j <= num16; j++)
				{
					float num17 = (float)j * step + num14;
					Vector3 val3 = field.Origin + field.Along * num17 + field.Inward * num13;
					float num18 = val3.x - position.x;
					float num19 = val3.z - position.z;
					if (!(num18 * num18 + num19 * num19 > reach * reach) && field.Contains(val3) && !(field.EdgeDistance(val3) < num2))
					{
						val3.y = Geometry.Ground(val3);
						if (!IsFailed(val3) && PairOk(val3, spec) && Grows(val3, spec))
						{
							return val3;
						}
					}
				}
			}
			return null;
		}

		internal static void BeginGhost()
		{
			inGhost = true;
			Redirected = false;
			blocking = false;
		}

		internal static bool Redirect(Player player, bool hit, Vector3 aim, out Vector3 point)
		{
			//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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			if (!inGhost || (Object)(object)player != (Object)(object)Player.m_localPlayer || !Plugin.On || !Plugin.HoldsCultivator(player))
			{
				return false;
			}
			Piece selectedPiece = player.GetSelectedPiece();
			if (!IsPlantable(selectedPiece))
			{
				return false;
			}
			if (PlantEasily)
			{
				if (!warnedPlantEasily)
				{
					warnedPlantEasily = true;
					Plugin.Log.LogWarning((object)"Felder: PlantEasily ist installiert (setzt ganze Raster je Klick), deshalb pflanzen Felder nicht automatisch.");
				}
				return false;
			}
			RefreshCaches();
			FieldView fieldView = (hit ? Plugin.At(aim) : null);
			FieldView fieldView2 = fieldView;
			if ((Object)(object)fieldView2 == (Object)null && holding)
			{
				fieldView2 = Plugin.Nearest(((Component)player).transform.position, Reach);
			}
			Field field = (((Object)(object)fieldView2 != (Object)null) ? fieldView2.Data : null);
			if (field == null)
			{
				slot = null;
				return false;
			}
			Spec spec = SpecOf(selectedPiece);
			if ((Object)(object)fieldView2 != (Object)(object)slotField || spec != slotSpec || Time.time >= searchUntil)
			{
				slotField = fieldView2;
				slotSpec = spec;
				searchUntil = Time.time + 0.25f;
				slot = Search(player, field, spec);
			}
			if (!slot.HasValue)
			{
				blocking = (Object)(object)fieldView != (Object)null;
				return false;
			}
			point = slot.Value;
			target = point;
			Redirected = true;
			return true;
		}

		internal static void Capture(Player player)
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Redirected && (Object)(object)player.m_placementGhost != (Object)null)
			{
				captured = player.m_placementStatus;
				capturedPosition = player.m_placementGhost.transform.position;
			}
		}

		internal static void EndGhost(Player player, bool placing)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Invalid comparison between Unknown and I4
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			inGhost = false;
			GameObject placementGhost = player.m_placementGhost;
			lastValid = false;
			if ((Object)(object)placementGhost == (Object)null)
			{
				return;
			}
			if (Redirected)
			{
				Vector3 val = placementGhost.transform.position - capturedPosition;
				if (((Vector3)(ref val)).sqrMagnitude > 1E-06f)
				{
					placementGhost.transform.position = capturedPosition;
					player.m_placementStatus = captured;
					player.SetPlacementGhostValid((int)captured == 0);
				}
				PlacementStatus placementStatus = player.m_placementStatus;
				lastValid = (int)placementStatus == 0;
				if (!lastValid)
				{
					bool flag = (int)placementStatus == 4 || (int)placementStatus == 3;
					Failed[Key(target)] = Time.time + (flag ? 30f : 3f);
				}
			}
			else if (blocking || (placing && Time.time < autoClickUntil))
			{
				player.m_placementStatus = (PlacementStatus)5;
				player.SetPlacementGhostValid(false);
			}
		}

		internal static void Placed(Piece piece, Vector3 position)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (IsPlantable(piece))
			{
				Recent.Add((position, SpecOf(piece), Time.time + 3f));
				searchUntil = 0f;
				autoClickUntil = 0f;
			}
		}

		internal static void Update(Player? player, Piece? selected)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			Expire();
			if ((Object)(object)player == (Object)null || !IsPlantable(selected) || PlantEasily)
			{
				holding = false;
				noSeeds = false;
				return;
			}
			if (!ZInput.GetButton("Use") || Gc.TextInputActive() || InventoryGui.IsVisible() || Hud.IsPieceSelectionVisible() || Menu.IsVisible() || UnifiedPopup.IsVisible() || ((Character)player).IsDead() || (Object)(object)Plugin.Nearest(((Component)player).transform.position, Reach) == (Object)null)
			{
				holding = false;
				noSeeds = false;
				return;
			}
			holding = true;
			if (noSeeds || Time.time < nextAuto)
			{
				return;
			}
			if (!lastValid)
			{
				nextAuto = Time.time + 0.25f;
				if (Time.time >= nextNoSlot)
				{
					nextNoSlot = Time.time + 3f;
					Gc.TopLeft(GcLoc.Get("gccf_no_slot", Array.Empty<object>()));
				}
				return;
			}
			ItemData rightItem = ((Humanoid)player).GetRightItem();
			if (rightItem == null || !((Character)player).HaveStamina(rightItem.m_shared.m_attack.m_attackStamina))
			{
				if ((Object)(object)Hud.instance != (Object)null)
				{
					Hud.instance.StaminaBarEmptyFlash();
				}
				nextAuto = Time.time + 0.5f;
			}
			else if (!player.m_noPlacementCost && !player.HaveRequirements(selected, (RequirementMode)0))
			{
				noSeeds = true;
				Gc.TopLeft(GcLoc.Get("gccf_no_seeds", Array.Empty<object>()));
			}
			else
			{
				player.m_placePressedTime = Time.time;
				autoClickUntil = Time.time + 0.3f;
				nextAuto = Time.time + Mathf.Max(0.1f, GcFields.Get<float>("interval", 0.5f));
			}
		}

		private static void Expire()
		{
			Expired.Clear();
			foreach (KeyValuePair<long, float> item in Failed)
			{
				if (Time.time > item.Value)
				{
					Expired.Add(item.Key);
				}
			}
			foreach (long item2 in Expired)
			{
				Failed.Remove(item2);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class FieldGhostPatch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Planting.BeginGhost();
			}
		}

		[HarmonyPriority(800)]
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Planting.Capture(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class FieldGhostLastPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(Player __instance, bool flashGuardStone)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Planting.EndGhost(__instance, flashGuardStone);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	internal static class FieldRayPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(Player __instance, ref bool __result, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (Planting.Redirect(__instance, __result, point, out var point2))
			{
				point = point2;
				normal = Vector3.up;
				piece = null;
				heightmap = Heightmap.FindHeightmap(point2);
				waterSurface = null;
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	internal static class FieldPlacedPatch
	{
		private static void Postfix(Player __instance, Piece piece, Vector3 pos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Planting.Placed(piece, pos);
			}
		}
	}
	public enum FieldColor
	{
		Yellow,
		Orange,
		Red,
		Green,
		Turquoise,
		Blue,
		Purple,
		White
	}
	internal static class Plugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action <0>__CreateMarker;

			public static Action <1>__AttachView;

			public static PopupButtonCallback <2>__Pop;
		}

		internal const string MarkerName = "GC_FieldMarker";

		private const string CultivatorTable = "_CultivatorPieceTable";

		private const float CloseRadius = 1f;

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<FieldColor> Tint = null;

		internal static ConfigEntry<int> FillOpacity = null;

		internal static ConfigEntry<int> LineOpacity = null;

		internal static readonly List<Vector3> Draft = new List<Vector3>();

		private static LineRenderer? draftLine;

		private static bool shownFields;

		private static float nextHint;

		private static Piece? lastSelected;

		internal static Piece? MarkerPiece;

		private const float MaxRadius = 100f;

		internal static bool PrefabAvailable
		{
			get
			{
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					return (Object)(object)ZNetScene.instance.GetPrefab("GC_Field") != (Object)null;
				}
				return false;
			}
		}

		internal static bool On
		{
			get
			{
				if (Enabled.Value && GcFields.Get<bool>("enabled", true) && PrefabAvailable && ClientPlugin.Allowed)
				{
					return ClientPlugin.OnServer;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ClientPlugin.Log;
			Enabled = Gc.Bind<bool>(Config, "12 - Fields", "Enabled", true, "Felder mit dem Kultivator anzeigen, markieren und in Reihen bepflanzen (die Regeln gibt GC_Server vor).", (AcceptableValueBase)null);
			Tint = Gc.Bind<FieldColor>(Config, "12 - Fields", "Color", FieldColor.Yellow, "Farbe von Fläche und Rand (Yellow = Valheim-Gelb).", (AcceptableValueBase)null);
			FillOpacity = Gc.Bind<int>(Config, "12 - Fields", "FillOpacity", 10, "Deckkraft der Fläche in Prozent (nachts automatisch gedämpft).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100));
			LineOpacity = Gc.Bind<int>(Config, "12 - Fields", "LineOpacity", 55, "Deckkraft des Rands in Prozent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100));
			Tint.SettingChanged += delegate
			{
				Materials.Changed();
			};
			FillOpacity.SettingChanged += delegate
			{
				Materials.Changed();
			};
			LineOpacity.SettingChanged += delegate
			{
				Materials.Changed();
			};
			PrefabManager.OnVanillaPrefabsAvailable += CreateMarker;
			PrefabManager.OnPrefabsRegistered += AttachView;
		}

		private static void AttachView()
		{
			Planting.ResetCaches();
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("GC_Field") : null);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)"Felder: Welt-Objekt GC_Field fehlt (GC_Server zu alt oder nicht installiert), Felder bleiben aus.");
			}
			else if ((Object)(object)val.GetComponent<FieldView>() == (Object)null)
			{
				val.AddComponent<FieldView>();
			}
		}

		internal static bool HoldsCultivator(Player? player)
		{
			PieceTable val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetRightItem() : null)?.m_shared?.m_buildPieces;
			if ((Object)(object)val != (Object)null)
			{
				return ((Object)val).name == "_CultivatorPieceTable";
			}
			return false;
		}

		internal static bool IsMarker(Piece? piece)
		{
			if ((Object)(object)piece != (Object)null)
			{
				return (Object)(object)((Component)piece).GetComponent<FieldMarker>() != (Object)null;
			}
			return false;
		}

		private static void CreateMarker()
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreateMarker;
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("GC_FieldMarker", "cultivate_v2");
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Felder: cultivate_v2 nicht gefunden, kein Menüeintrag „Feld markieren“.");
				return;
			}
			TerrainOp[] componentsInChildren = val.GetComponentsInChildren<TerrainOp>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			TerrainModifier[] componentsInChildren2 = val.GetComponentsInChildren<TerrainModifier>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			val.AddComponent<FieldMarker>();
			Piece? obj = (MarkerPiece = val.GetComponent<Piece>());
			obj.m_name = GcLoc.Get("gccf_marker_name", Array.Empty<object>());
			obj.m_description = GcLoc.Get("gccf_marker_desc", Array.Empty<object>());
			obj.m_icon = Icon();
			obj.m_resources = (Requirement[])(object)new Requirement[0];
			obj.m_craftingStation = null;
			obj.m_cultivatedGroundOnly = false;
			obj.m_vegetationGroundOnly = false;
			obj.m_onlyInBiome = (Biome)0;
			PieceManager.Instance.AddPiece(new CustomPiece(val, true, new PieceConfig
			{
				PieceTable = "_CultivatorPieceTable"
			}));
			Log.LogInfo((object)"Felder: Menüeintrag „Feld markieren“ im Kultivator angelegt.");
		}

		private static Sprite Icon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Vector2[] array = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(10f, 14f),
				new Vector2(54f, 10f),
				new Vector2(50f, 54f),
				new Vector2(14f, 46f)
			};
			List<Vector3> list = new List<Vector3>();
			Vector2[] array2 = array;
			foreach (Vector2 val2 in array2)
			{
				list.Add(new Vector3(val2.x, 0f, val2.y));
			}
			Color val3 = default(Color);
			for (int j = 0; j < 64; j++)
			{
				for (int k = 0; k < 64; k++)
				{
					((Color)(ref val3))..ctor(0f, 0f, 0f, 0f);
					if (Geometry.Contains(list, (float)k + 0.5f, (float)j + 0.5f))
					{
						((Color)(ref val3))..ctor(0.3f, 0.8f, 0.3f, 0.6f);
						if (j / 6 % 2 == 0 && k % 6 < 3)
						{
							((Color)(ref val3))..ctor(0.45f, 0.3f, 0.15f, 1f);
						}
					}
					if (Geometry.EdgeDistance(list, new Vector3((float)k + 0.5f, 0f, (float)j + 0.5f)) < 1.6f)
					{
						((Color)(ref val3))..ctor(0.4f, 1f, 0.4f, 1f);
					}
					array2 = array;
					for (int i = 0; i < array2.Length; i++)
					{
						if (Vector2.Distance(array2[i], new Vector2((float)k, (float)j)) < 3.5f)
						{
							((Color)(ref val3))..ctor(1f, 0.9f, 0.3f, 1f);
						}
					}
					val.SetPixel(k, j, val3);
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}

		internal static void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)MarkerPiece != (Object)null && (Object)(object)localPlayer != (Object)null && MarkerPiece.m_enabled != On)
			{
				MarkerPiece.m_enabled = On;
				localPlayer.UpdateAvailablePiecesList();
			}
			int num;
			if ((Object)(object)localPlayer != (Object)null && On)
			{
				num = (HoldsCultivator(localPlayer) ? 1 : 0);
				if (num != 0)
				{
					Materials.Tick();
				}
			}
			else
			{
				num = 0;
			}
			ShowFields((byte)num != 0);
			if (num == 0)
			{
				if (Draft.Count > 0)
				{
					Draft.Clear();
				}
				UpdateDraftLine(null);
				Planting.Update(null, null);
				lastSelected = null;
				return;
			}
			Piece selectedPiece = localPlayer.GetSelectedPiece();
			if ((Object)(object)selectedPiece != (Object)(object)lastSelected)
			{
				lastSelected = selectedPiece;
				Hint(selectedPiece);
			}
			UpdateDraftLine(IsMarker(selectedPiece) ? localPlayer : null);
			Planting.Update(localPlayer, selectedPiece);
		}

		private static void ShowFields(bool show)
		{
			if (!show && !shownFields)
			{
				return;
			}
			shownFields = show;
			foreach (FieldView item in FieldView.All)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.Show(show);
				}
			}
		}

		private static void Hint(Piece? selected)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time < nextHint) && !((Object)(object)selected == (Object)null))
			{
				if (IsMarker(selected))
				{
					nextHint = Time.time + 60f;
					Gc.TopLeft(GcLoc.Get("gccf_hint_marker", Array.Empty<object>()));
				}
				else if (Planting.IsPlantable(selected) && !Planting.PlantEasily && (Object)(object)Nearest(((Component)Player.m_localPlayer).transform.position, 30f) != (Object)null)
				{
					nextHint = Time.time + 120f;
					Gc.TopLeft(GcLoc.Get("gccf_hint_plant", Array.Empty<object>()));
				}
			}
		}

		private static void UpdateDraftLine(Player? player)
		{
			//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_004b: Expected O, but got Unknown
			//IL_00a9: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || Draft.Count == 0)
			{
				if ((Object)(object)draftLine != (Object)null)
				{
					((Renderer)draftLine).enabled = false;
				}
				return;
			}
			if ((Object)(object)draftLine == (Object)null)
			{
				GameObject val = new GameObject("GC_FieldDraft");
				Object.DontDestroyOnLoad((Object)val);
				draftLine = val.AddComponent<LineRenderer>();
				draftLine.useWorldSpace = true;
				draftLine.widthMultiplier = 0.07f;
				((Renderer)draftLine).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)draftLine).receiveShadows = false;
				((Renderer)draftLine).material = Materials.Draft;
			}
			List<Vector3> list = new List<Vector3>();
			foreach (Vector3 item in Draft)
			{
				list.Add(item + Vector3.up * 0.15f);
			}
			GameObject placementGhost = player.m_placementGhost;
			if ((Object)(object)placementGhost != (Object)null && placementGhost.activeSelf)
			{
				list.Add(placementGhost.transform.position + Vector3.up * 0.15f);
			}
			((Renderer)draftLine).enabled = true;
			draftLine.positionCount = list.Count;
			draftLine.SetPositions(list.ToArray());
		}

		internal static void Click(Player player)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = player.m_placementGhost;
			if ((Object)(object)placementGhost == (Object)null || !placementGhost.activeSelf)
			{
				return;
			}
			Vector3 position = placementGhost.transform.position;
			position.y = Geometry.Ground(position);
			if (Draft.Count > 0 && Flat(position, Draft[0]) <= 1f)
			{
				if (Draft.Count >= 3)
				{
					Close(player);
				}
				else
				{
					Gc.TopLeft(GcLoc.Get("gccf_need_three", Array.Empty<object>()));
				}
				return;
			}
			if (Draft.Count == 0 && (Object)(object)At(position) != (Object)null)
			{
				Gc.TopLeft(GcLoc.Get("gccf_inside_other", Array.Empty<object>()));
				return;
			}
			int num = GcFields.Get<int>("maxPoints", 32);
			if (num > 0 && Draft.Count >= num)
			{
				Gc.TopLeft(GcLoc.Get("gccf_too_many", new object[1] { num }));
			}
			else if (Draft.Count <= 0 || EdgeAllowed(Draft[Draft.Count - 1], position, Draft.Count - 1))
			{
				Draft.Add(position);
			}
		}

		private static float Flat(Vector3 a, Vector3 b)
		{
			//IL_0016: 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)
			a.y = (b.y = 0f);
			return Vector3.Distance(a, b);
		}

		private static bool EdgeAllowed(Vector3 from, Vector3 to, int fromIndex, bool closing = false)
		{
			//IL_0048: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			float num = GcFields.Get<float>("maxEdge", 50f);
			if (num > 0f && Flat(from, to) > num)
			{
				Gc.TopLeft(GcLoc.Get("gccf_too_long", new object[1] { num.ToString("0.#") }));
				return false;
			}
			if (Flat(from, to) < 0.3f)
			{
				return false;
			}
			for (int i = 0; i + 1 < Draft.Count; i++)
			{
				if (i != fromIndex - 1 && i + 1 != fromIndex && (!closing || i != 0) && Geometry.Crosses(Draft[i], Draft[i + 1], from, to))
				{
					Gc.TopLeft(GcLoc.Get("gccf_crossing", Array.Empty<object>()));
					return false;
				}
			}
			foreach (FieldView item in FieldView.All)
			{
				Field field = (((Object)(object)item != (Object)null) ? item.Data : null);
				if (field == null)
				{
					continue;
				}
				if (field.Contains(to))
				{
					Gc.TopLeft(GcLoc.Get("gccf_overlap", Array.Empty<object>()));
					return false;
				}
				int num2 = 0;
				int index = field.Points.Count - 1;
				while (num2 < field.Points.Count)
				{
					if (Geometry.Crosses(field.Points[index], field.Points[num2], from, to))
					{
						Gc.TopLeft(GcLoc.Get("gccf_overlap", Array.Empty<object>()));
						return false;
					}
					index = num2++;
				}
			}
			return true;
		}

		private static void Close(Player player)
		{
			//IL_0011: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			if (!EdgeAllowed(Draft[Draft.Count - 1], Draft[0], Draft.Count - 1, closing: true))
			{
				return;
			}
			List<Vector3> list = new List<Vector3>(Draft);
			if (Mathf.Abs(Geometry.SignedArea(list)) < 1f)
			{
				Gc.TopLeft(GcLoc.Get("gccf_too_small", Array.Empty<object>()));
				return;
			}
			Vector3 b = Field.Centroid(list);
			foreach (Vector3 item in list)
			{
				if (Flat(item, b) > 100f)
				{
					Gc.TopLeft(GcLoc.Get("gccf_too_big", new object[1] { 100f.ToString("0") }));
					return;
				}
			}
			foreach (FieldView item2 in FieldView.All)
			{
				Field field = (((Object)(object)item2 != (Object)null) ? item2.Data : null);
				if (field != null && Geometry.Overlaps(list, field.Points))
				{
					Gc.TopLeft(GcLoc.Get("gccf_overlap", Array.Empty<object>()));
					return;
				}
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("GC_Field") : null);
			if ((Object)(object)val == (Object)null)
			{
				Gc.TopLeft(GcLoc.Get("gccf_no_server", Array.Empty<object>()));
				return;
			}
			Vector3 val2 = Field.Centroid(list);
			val2.y = Geometry.Ground(val2);
			GameObject val3 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity);
			ZNetView component = val3.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				Object.Destroy((Object)(object)val3);
				return;
			}
			Field.Write(component.GetZDO(), list, player.GetPlayerID(), player.GetPlayerName(), GcGuildInfo.OwnGuildId());
			Draft.Clear();
			Gc.TopLeft(GcLoc.Get("gccf_closed", new object[1] { Mathf.RoundToInt(Mathf.Abs(Geometry.SignedArea(list))) }));
		}

		internal static bool RightClick(Player player)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			if (Draft.Count > 0)
			{
				Draft.RemoveAt(Draft.Count - 1);
				return true;
			}
			FieldView view = AimedField(player);
			if ((Object)(object)view == (Object)null)
			{
				return false;
			}
			Field data = view.Data;
			if (data == null)
			{
				return false;
			}
			string text = Denied(player, data);
			if (text != null)
			{
				Gc.TopLeft(text);
				return true;
			}
			string text2 = GcLoc.Get("gccf_remove_title", Array.Empty<object>());
			string text3 = GcLoc.Get("gccf_remove_text", Array.Empty<object>());
			PopupButtonCallback val = delegate
			{
				UnifiedPopup.Pop();
				Remove(view);
			};
			object obj = <>O.<2>__Pop;
			if (obj == null)
			{
				PopupButtonCallback val2 = UnifiedPopup.Pop;
				<>O.<2>__Pop = val2;
				obj = (object)val2;
			}
			UnifiedPopup.Push((PopupBase)new YesNoPopup(text2, text3, val, (PopupButtonCallback)obj, false, false));
			return true;
		}

		private static string? Denied(Player player, Field data)
		{
			bool canChangeServer = GcMenu.CanChangeServer;
			bool flag = data.Creator != 0L && data.Creator == player.GetPlayerID();
			bool flag2 = data.Guild >= 0 && GcGuildInfo.OwnGuildId() == data.Guild && GcGuildInfo.IsLeader();
			switch (GcFields.Get<int>("removeBy", 0))
			{
			case 1:
				if (!(flag || canChangeServer))
				{
					return GcLoc.Get("gccf_denied_creator", Array.Empty<object>());
				}
				return null;
			case 2:
				if (!(flag || canChangeServer || flag2))
				{
					return GcLoc.Get("gccf_denied_guild", Array.Empty<object>());
				}
				return null;
			case 3:
				if (!canChangeServer)
				{
					return GcLoc.Get("gccf_denied_admin", Array.Empty<object>());
				}
				return null;
			default:
				return null;
			}
		}

		private static void Remove(FieldView view)
		{
			if (!((Object)(object)view == (Object)null))
			{
				ZNetView view2 = view.View;
				if ((Object)(object)view2 != (Object)null && view2.IsValid())
				{
					view2.ClaimOwnership();
					ZNetScene.instance.Destroy(((Component)view).gameObject);
					Gc.TopLeft(GcLoc.Get("gccf_removed", Array.Empty<object>()));
				}
			}
		}

		internal static bool CancelDraft()
		{
			Player localPlayer = Player.m_localPlayer;
			if (Draft.Count == 0 || (Object)(object)localPlayer == (Object)null || !IsMarker(localPlayer.GetSelectedPiece()) || InventoryGui.IsVisible() || Minimap.IsOpen() || Console.IsVisible() || TextInput.IsVisible() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible() || UnifiedPopup.IsVisible() || Hud.InRadial() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.m_wasFocused))
			{
				return false;
			}
			Draft.Clear();
			Gc.TopLeft(GcLoc.Get("gccf_cancel", Array.Empty<object>()));
			return true;
		}

		private static FieldView? AimedField(Player player)
		{
			//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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GameCamera.instance == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, player.m_placeRayMask))
			{
				return null;
			}
			Piece val2 = (((Object)(object)player.m_placementGhost != (Object)null) ? player.m_placementGhost.GetComponent<Piece>() : null);
			float num = player.m_maxPlaceDistance + (float)(((Object)(object)val2 != (Object)null) ? val2.m_extraPlacementDistance : 0);
			if (!(Vector3.Distance(((Character)player).m_eye.position, ((RaycastHit)(ref val)).point) <= num))
			{
				return null;
			}
			return At(((RaycastHit)(ref val)).point);
		}

		internal static FieldView? At(Vector3 point)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			foreach (FieldView item in FieldView.All)
			{
				Field field = (((Object)(object)item != (Object)null) ? item.Data : null);
				if (field != null && point.x >= field.MinX && point.x <= field.MaxX && point.z >= field.MinZ && point.z <= field.MaxZ && field.Contains(point))
				{
					return item;
				}
			}
			return null;
		}

		internal static FieldView? Nearest(Vector3 point, float range)
		{
			//IL_0034: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			FieldView result = null;
			float num = range;
			foreach (FieldView item in FieldView.All)
			{
				Field field = (((Object)(object)item != (Object)null) ? item.Data : null);
				if (field != null && !(point.x < field.MinX - range) && !(point.x > field.MaxX + range) && !(point.z < field.MinZ - range) && !(point.z > field.MaxZ + range))
				{
					float num2 = (field.Contains(point) ? 0f : field.EdgeDistance(point));
					if (num2 <= num)
					{
						result = item;
						num = num2;
					}
				}
			}
			return result;
		}
	}
	public class FieldMarker : MonoBehaviour
	{
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	internal static class FieldClickPatch
	{
		[HarmonyPriority(800)]
		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Plugin.IsMarker(piece))
			{
				return true;
			}
			__result = false;
			if (Plugin.On)
			{
				Plugin.Click(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
	internal static class FieldRightClickPatch
	{
		private static bool Prefix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Plugin.On || !ZInput.GetButtonDown("BuildMenu") || Hud.IsPieceSelectionVisible() || PlayerController.HasInputDelay || Hud.InRadial() || !Plugin.IsMarker(__instance.GetSelectedPiece()))
			{
				return true;
			}
			return !Plugin.RightClick(__instance);
		}
	}
	[HarmonyPatch(typeof(Menu), "Update")]
	internal static class FieldEscapePatch
	{
		private static bool Prefix()
		{
			if (ZInput.GetKeyDown((KeyCode)27, true) && !Menu.IsVisible())
			{
				return !Plugin.CancelDraft();
			}
			return true;
		}
	}
	internal sealed class Field
	{
		public readonly List<Vector3> Points = new List<Vector3>();

		public long Creator;

		public string CreatorName = "";

		public int Guild = -1;

		public Vector3 Along;

		public Vector3 Inward;

		public float MinX;

		public float MaxX;

		public float MinZ;

		public float MaxZ;

		internal static readonly int PointsHash = StringExtensionMethods.GetStableHashCode("gc_field_pts");

		internal static readonly int CreatorHash = StringExtensionMethods.GetStableHashCode("gc_field_creator");

		internal static readonly int CreatorNameHash = StringExtensionMethods.GetStableHashCode("gc_field_creator_name");

		internal static readonly int GuildHash = StringExtensionMethods.GetStableHashCode("gc_field_guild");

		public Vector3 Origin => Points[0];

		public float Area => Mathf.Abs(Geometry.SignedArea(Points));

		public static Field? Read(ZDO zdo)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			byte[] byteArray = zdo.GetByteArray(PointsHash, (byte[])null);
			if (byteArray == null || byteArray.Length < 4)
			{
				return null;
			}
			Field field = new Field
			{
				Creator = zdo.GetLong(CreatorHash, 0L),
				CreatorName = zdo.GetString(CreatorNameHash, ""),
				Guild = zdo.GetInt(GuildHash, -1)
			};
			try
			{
				ZPackage val = new ZPackage(byteArray);
				int num = val.ReadInt();
				for (int i = 0; i < num && i < 4096; i++)
				{
					field.Points.Add(val.ReadVector3());
				}
			}
			catch
			{
				return null;
			}
			if (field.Points.Count < 3)
			{
				return null;
			}
			return field.Prepare();
		}

		public static void Write(ZDO zdo, List<Vector3> points, long creator, string creatorName, int guild)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(points.Count);
			foreach (Vector3 point in points)
			{
				val.Write(point);
			}
			zdo.Set(PointsHash, val.GetArray());
			zdo.Set(CreatorHash, creator);
			zdo.Set(CreatorNameHash, creatorName);
			zdo.Set(GuildHash, guild, false);
		}

		public Field? Prepare()
		{
			//IL_0007: 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_0018: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Points[1] - Points[0];
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				return null;
			}
			Along = ((Vector3)(ref val)).normalized;
			Inward = new Vector3(0f - Along.z, 0f, Along.x);
			if (Geometry.SignedArea(Points) < 0f)
			{
				Inward = -Inward;
			}
			MinX = (MinZ = float.MaxValue);
			MaxX = (MaxZ = float.MinValue);
			foreach (Vector3 point in Points)
			{
				MinX = Mathf.Min(MinX, point.x);
				MaxX = Mathf.Max(MaxX, point.x);
				MinZ = Mathf.Min(MinZ, point.z);
				MaxZ = Mathf.Max(MaxZ, point.z);
			}
			return this;
		}

		public bool Contains(Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Geometry.Contains(Points, point.x, point.z);
		}

		public float EdgeDistance(Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Geometry.EdgeDistance(Points, point);
		}

		public static Vector3 Centroid(List<Vector3> points)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.zero;
			foreach (Vector3 point in points)
			{
				val += point;
			}
			return val / (float)Mathf.Max(1, points.Count);
		}
	}
	internal static class Geometry
	{
		public static bool Contains(List<Vector3> polygon, float x, float z)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			int num = 0;
			int index = polygon.Count - 1;
			while (num < polygon.Count)
			{
				Vector3 val = polygon[num];
				Vector3 val2 = polygon[index];
				if (val.z > z != val2.z > z && x < (val2.x - val.x) * (z - val.z) / (val2.z - val.z) + val.x)
				{
					flag = !flag;
				}
				index = num++;
			}
			return flag;
		}

		public static float SignedArea(List<Vector3> polygon)
		{
			//IL_0016: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			int num2 = 0;
			int index = polygon.Count - 1;
			while (num2 < polygon.Count)
			{
				num += polygon[index].x * polygon[num2].z - polygon[num2].x * polygon[index].z;
				index = num2++;
			}
			return num * 0.5f;
		}

		public static float EdgeDistance(List<Vector3> polygon, Vector3 point)
		{
			//IL_0008: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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)
			float num = float.MaxValue;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(point.x, point.z);
			int num2 = 0;
			int index = polygon.Count - 1;
			Vector2 val2 = default(Vector2);
			while (num2 < polygon.Count)
			{
				((Vector2)(ref val2))..ctor(polygon[index].x, polygon[index].z);
				Vector2 val3 = new Vector2(polygon[num2].x, polygon[num2].z) - val2;
				float num3 = ((((Vector2)(ref val3)).sqrMagnitude > 0f) ? Mathf.Clamp01(Vector2.Dot(val - val2, val3) / ((Vector2)(ref val3)).sqrMagnitude) : 0f);
				num = Mathf.Min(num, Vector2.Distance(val, val2 + val3 * num3));
				index = num2++;
			}
			return num;
		}

		public static bool Crosses(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			float num = Cross(c, d, a);
			float num2 = Cross(c, d, b);
			float num3 = Cross(a, b, c);
			float num4 = Cross(a, b, d);
			if ((num > 0f && num2 < 0f) || (num < 0f && num2 > 0f))
			{
				if (!(num3 > 0f) || !(num4 < 0f))
				{
					if (num3 < 0f)
					{
						return num4 > 0f;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static float Cross(Vector3 a, Vector3 b, Vector3 p)
		{
			//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)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			return (b.x - a.x) * (p.z - a.z) - (b.z - a.z) * (p.x - a.x);
		}

		public static bool Overlaps(List<Vector3> a, List<Vector3> b)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0023: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int index = a.Count - 1;
			while (num < a.Count)
			{
				int num2 = 0;
				int index2 = b.Count - 1;
				while (num2 < b.Count)
				{
					if (Crosses(a[index], a[num], b[index2], b[num2]))
					{
						return true;
					}
					index2 = num2++;
				}
				index = num++;
			}
			if (!Contains(b, a[0].x, a[0].z))
			{
				return Contains(a, b[0].x, b[0].z);
			}
			return true;
		}

		public static List<int> Triangulate(List<Vector3> polygon)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			bool flag = SignedArea(polygon) > 0f;
			for (int i = 0; i < polygon.Count; i++)
			{
				list2.Add(flag ? i : (polygon.Count - 1 - i));
			}
			int num = 0;
			while (list2.Count > 3 && num++ < 10000)
			{
				bool flag2 = false;
				for (int j = 0; j < list2.Count; j++)
				{
					int num2 = list2[(j + list2.Count - 1) % list2.Count];
					int num3 = list2[j];
					int num4 = list2[(j + 1) % list2.Count];
					Vector3 a = polygon[num2];
					Vector3 b = polygon[num3];
					Vector3 val = polygon[num4];
					if (Cross(a, b, val) <= 0f)
					{
						continue;
					}
					bool flag3 = true;
					foreach (int item in list2)
					{
						if (item != num2 && item != num3 && item != num4 && InTriangle(polygon[item], a, b, val))
						{
							flag3 = false;
							break;
						}
					}
					if (flag3)
					{
						list.Add(num2);
						list.Add(num3);
						list.Add(num4);
						list2.RemoveAt(j);
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					break;
				}
			}
			for (int k = 1; k + 1 < list2.Count; k++)
			{
				list.Add(list2[0]);
				list.Add(list2[k]);
				list.Add(list2[k + 1]);
			}
			return list;
		}

		private static bool InTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_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_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)
			if (Cross(a, b, p) >= 0f && Cross(b, c, p) >= 0f)
			{
				return Cross(c, a, p) >= 0f;
			}
			return false;
		}

		public static float Ground(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			float result = default(float);
			if (Heightmap.GetHeight(point, ref result))
			{
				return result;
			}
			if (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGroundHeight(point, ref result))
			{
				return point.y;
			}
			return result;
		}
	}
	public class FieldView : MonoBehaviour
	{
		internal static readonly List<FieldView> All = new List<FieldView>();

		private const float Lift = 0.12f;

		private const int MaxVertices = 6000;

		private static int heightFrame = -1;

		private ZNetView? nview;

		private Field? cached;

		private uint revision = uint.MaxValue;

		private GameObject? visual;

		private LineRenderer? outline;

		private Mesh? mesh;

		private bool shown;

		private bool topologyDirty = true;

		private bool heightsDone;

		private float nextHeights;

		private Vector3[] flatOutline = (Vector3[])(object)new Vector3[0];

		private Vector3[] vertices = (Vector3[])(object)new Vector3[0];

		private int[] triangles = new int[0];

		internal ZNetView? View => nview;

		internal Field? Data
		{
			get
			{
				if ((Object)(object)nview == (Object)null || !nview.IsValid())
				{
					return null;
				}
				ZDO zDO = nview.GetZDO();
				if (zDO.DataRevision != revision)
				{
					revision = zDO.DataRevision;
					cached = Field.Read(zDO);
					topologyDirty = true;
					heightsDone = false;
				}
				return cached;
			}
		}

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

		private void OnDestroy()
		{
			All.Remove(this);
			if ((Object)(object)visual != (Object)null)
			{
				Object.Destroy((Object)(object)visual);
			}
			if ((Object)(object)mesh != (Object)null)
			{
				Object.Destroy((Object)(object)mesh);
			}
		}

		internal void Show(bool show)
		{
			if (show != shown)
			{
				shown = show;
				if ((Object)(object)visual != (Object)null)
				{
					visual.SetActive(show && cached != null);
				}
			}
			if (!show)
			{
				return;
			}
			Field data = Data;
			if (data == null)
			{
				if ((Object)(object)visual != (Object)null)
				{
					visual.SetActive(false);
				}
				return;
			}
			if (topologyDirty)
			{
				BuildTopology(data);
			}
			RefreshHeights(data);
		}

		private void BuildTopology(Field data)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Expected O, but got Unknown
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Expected O, but got Unknown
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			topologyDirty = false;
			heightsDone = false;
			List<Vector3> list = new List<Vector3>();
			for (int i = 0; i < data.Points.Count; i++)
			{
				Vector3 val = data.Points[i];
				Vector3 val2 = data.Points[(i + 1) % data.Points.Count];
				int num = Mathf.Clamp(Mathf.CeilToInt(Vector3.Distance(val, val2)), 1, 200);
				for (int j = 0; j < num; j++)
				{
					list.Add(Vector3.Lerp(val, val2, (float)j / (float)num));
				}
			}
			flatOutline = list.ToArray();
			List<int> list2 = Geometry.Triangulate(data.Points);
			float num2 = 1f;
			for (int k = 0; k < 12; k++)
			{
				int num3 = 0;
				for (int l = 0; l + 2 < list2.Count; l += 3)
				{
					int num4 = Steps(data.Points[list2[l]], data.Points[list2[l + 1]], data.Points[list2[l + 2]], num2);
					num3 += (num4 + 1) * (num4 + 2) / 2;
				}
				if (num3 <= 6000)
				{
					break;
				}
				num2 *= Mathf.Sqrt((float)num3 / 6000f) * 1.05f;
			}
			List<Vector3> list3 = new List<Vector3>();
			List<int> list4 = new List<int>();
			for (int m = 0; m + 2 < list2.Count; m += 3)
			{
				Subdivide(data.Points[list2[m]], data.Points[list2[m + 1]], data.Points[list2[m + 2]], num2, list3, list4);
			}
			vertices = list3.ToArray();
			triangles = list4.ToArray();
			if ((Object)(object)visual == (Object)null)
			{
				visual = new GameObject("GC_FieldVisual");
				outline = visual.AddComponent<LineRenderer>();
				outline.useWorldSpace = true;
				outline.loop = true;
				outline.widthMultiplier = 0.05f;
				((Renderer)outline).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)outline).receiveShadows = false;
				((Renderer)outline).material = Materials.Line;
				GameObject val3 = new GameObject("fill");
				val3.transform.SetParent(visual.transform, false);
				mesh = new Mesh
				{
					name = "GC_FieldFill",
					indexFormat = (IndexFormat)1
				};
				val3.AddComponent<MeshFilter>().sharedMesh = mesh;
				MeshRenderer obj = val3.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = Materials.Fill;
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
			}
			visual.SetActive(false);
		}

		private void RefreshHeights(Field data)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			if ((!heightsDone || !(Time.time < nextHeights)) && heightFrame != Time.frameCount && (!heightsDone || Near(data)))
			{
				heightFrame = Time.frameCount;
				heightsDone = true;
				nextHeights = Time.time + 3f;
				Vector3[] array = (Vector3[])(object)new Vector3[flatOutline.Length];
				for (int i = 0; i < array.Length; i++)
				{
					Vector3 val = flatOutline[i];
					val.y = Geometry.Ground(val) + 0.12f + 0.02f;
					array[i] = val;
				}
				outline.positionCount = array.Length;
				outline.SetPositions(array);
				for (int j = 0; j < vertices.Length; j++)
				{
					vertices[j].y = Geometry.Ground(vertices[j]) + 0.12f;
				}
				mesh.Clear();
				mesh.vertices = vertices;
				mesh.triangles = triangles;
				mesh.RecalculateBounds();
				visual.SetActive(shown);
			}
		}

		private static bool Near(Field data)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			if (position.x >= data.MinX - 64f && position.x <= data.MaxX + 64f && position.z >= data.MinZ - 64f)
			{
				return position.z <= data.MaxZ + 64f;
			}
			return false;
		}

		private static int Steps(Vector3 a, Vector3 b, Vector3 c, float cell)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			return Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(Vector3.Distance(a, b), Mathf.Max(Vector3.Distance(b, c), Vector3.Distance(c, a))) / cell), 1, 64);
		}

		private static void Subdivide(Vector3 a, Vector3 b, Vector3 c, float cell, List<Vector3> vertices, List<int> triangles)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing 

GC_Futterfolge.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Shared;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Futterfolge")]
[assembly: AssemblyTitle("GC_Futterfolge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Mods.Futterfolge
{
	internal static class FeedOrder
	{
		private sealed class Wait
		{
			public float Since;

			public float Last;
		}

		private sealed class Shown
		{
			public float Until;

			public int Place;

			public int Count;
		}

		private sealed class Food
		{
			public ItemDrop Item;

			public Vector3 Position;

			public float Distance;

			public int Left;
		}

		private sealed class Rival
		{
			public Character Animal;

			public MonsterAI AI;

			public float Level;

			public int Stars;

			public bool Pregnant;

			public ZDOID Id;
		}

		private readonly struct Reach
		{
			private readonly Vector3 center;

			private readonly float radius;

			private readonly bool limited;

			public Reach(Vector3 center, float radius)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				this.center = center;
				this.radius = radius;
				limited = true;
			}

			public bool Covers(Vector3 point)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if (limited)
				{
					Vector3 val = point - center;
					return ((Vector3)(ref val)).sqrMagnitude <= radius * radius;
				}
				return true;
			}
		}

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<float> RangeFactor = null;

		internal static ConfigEntry<float> WaitSeconds = null;

		internal static ConfigEntry<bool> PregnantLast = null;

		internal static ConfigEntry<bool> BestPartner = null;

		internal static ConfigEntry<bool> Wild = null;

		internal static ConfigEntry<bool> ShowRank = null;

		private static ManualLogSource log = null;

		private static bool reported;

		private static readonly int CareLevelHash = StringExtensionMethods.GetStableHashCode("gc_care_level");

		private static readonly int HolderHash = StringExtensionMethods.GetStableHashCode("gc_leash_holder");

		private static readonly int TiedHash = StringExtensionMethods.GetStableHashCode("gc_leash_tied");

		private static readonly int PostHash = StringExtensionMethods.GetStableHashCode("gc_leash_post");

		private static readonly int MaxLengthHash = StringExtensionMethods.GetStableHashCode("gc_leash_max");

		private static readonly int MateLevelHash = StringExtensionMethods.GetStableHashCode("gc_ff_mate_level");

		private const int OwnPathChecks = 3;

		private const int RivalPathChecks = 2;

		private const float WaitGap = 25f;

		private const float PathMemory = 20f;

		private const float RankMemory = 1f;

		private const float DefaultLeashLength = 10f;

		private static int itemMask;

		private static float nextCleanup;

		private static readonly Dictionary<Character, Wait> Waiting = new Dictionary<Character, Wait>();

		private static readonly Dictionary<long, KeyValuePair<bool, float>> Paths = new Dictionary<long, KeyValuePair<bool, float>>();

		private static readonly Dictionary<Character, Shown> Ranks = new Dictionary<Character, Shown>();

		internal static void Init(ConfigFile config, ManualLogSource logger)
		{
			log = logger;
			Enabled = Gc.BindSynced<bool>(config, "1 - Futter", "Enabled", true, "Futter-Reihenfolge: Zahme Tiere sehen Futter weiter (wenn ein Weg hinführt), und das Tier mit der höchsten Stufe einer Sorte frisst zuerst. Aus: wie Valheim.", (AcceptableValueBase)null);
			RangeFactor = Gc.BindSynced<float>(config, "1 - Futter", "RangeFactor", 2f, "Faktor auf Valheims Umkreis, in dem ein Tier Futter sucht (2 = doppelt so weit). Es frisst nur, wenn ein Weg hinführt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f));
			WaitSeconds = Gc.BindSynced<float>(config, "1 - Futter", "WaitSeconds", 60f, "So viele Sekunden lässt ein Tier ranghöheren den Vortritt; danach frisst es trotzdem (falls ein höheres nicht hinkommt). 0 = nie warten.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f));
			PregnantLast = Gc.BindSynced<bool>(config, "1 - Futter", "PregnantLast", true, "Trächtige Tiere stellen sich hinten an: Für die Zucht brauchen sie kein Futter, so werden zuerst die Tiere satt, die sich paaren können.", (AcceptableValueBase)null);
			Wild = Gc.BindSynced<bool>(config, "1 - Futter", "WildAnimals", false, "Auch wilde Tiere sehen Futter so weit (beim Zähmen). Eine Reihenfolge gibt es bei wilden Tieren nicht. Standard aus, damit das Zähmen nicht leichter wird.", (AcceptableValueBase)null);
			BestPartner = Gc.BindSynced<bool>(config, "2 - Zucht", "BestPartner", true, "Mit GC_Tiere: Für die Stufe des Jungen zählt der beste satte Partner beim Trächtigwerden (höchste Stufe im Partner-Umkreis), nicht das nächste Tier.", (AcceptableValueBase)null);
			ShowRank = Gc.Bind<bool>(config, "3 - Anzeige", "ShowRank", true, "Am hungrigen zahmen Tier anzeigen, an welcher Stelle es beim Fressen steht, und ob es gerade wartet.", (AcceptableValueBase)null);
		}

		internal static bool Handles(MonsterAI ai)
		{
			if (!Enabled.Value || !Plugin.Module.Allowed)
			{
				return false;
			}
			Character character = ((BaseAI)ai).m_character;
			if ((Object)(object)character == (Object)null || ai.m_consumeItems == null || ai.m_consumeItems.Count == 0)
			{
				return false;
			}
			if (!character.IsTamed())
			{
				return Wild.Value;
			}
			return true;
		}

		internal static ItemDrop? Find(MonsterAI ai, float maxRange)
		{
			Cleanup();
			Character character = ((BaseAI)ai).m_character;
			float range = maxRange * RangeFactor.Value;
			List<Food> foods = FoodAround(ai, character, range);
			bool reserved = false;
			ItemDrop val = (character.IsTamed() ? Reachable(ai, character, LeftAfterHigher(character, foods, range, out reserved)) : Reachable(ai, character, foods));
			if ((Object)(object)val == (Object)null && reserved)
			{
				if (KeepWaiting(character))
				{
					return null;
				}
				return Reachable(ai, character, foods);
			}
			StopWaiting(character);
			return val;
		}

		private static List<Food> FoodAround(MonsterAI ai, Character self, float range)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			if (itemMask == 0)
			{
				itemMask = LayerMask.GetMask(new string[1] { "item" });
			}
			List<Food> list = new List<Food>();
			HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>();
			Vector3 position = ((Component)self).transform.position;
			Reach reach = ReachOf(self, ai.m_consumeRange);
			Collider[] array = Physics.OverlapSphere(position, range, itemMask);
			foreach (Collider val in array)
			{
				ItemDrop val2 = (((Object)(object)val.attachedRigidbody != (Object)null) ? ((Component)val.attachedRigidbody).GetComponent<ItemDrop>() : null);
				if (!((Object)(object)val2 == (Object)null) && hashSet.Add(val2) && !((Object)(object)val2.m_nview == (Object)null) && val2.m_nview.IsValid() && ai.CanConsume(val2.m_itemData))
				{
					Vector3 position2 = ((Component)val2).transform.position;
					if (reach.Covers(position2))
					{
						list.Add(new Food
						{
							Item = val2,
							Position = position2,
							Distance = Vector3.Distance(position2, position),
							Left = Mathf.Max(1, val2.m_itemData.m_stack)
						});
					}
				}
			}
			list.Sort((Food a, Food b) => a.Distance.CompareTo(b.Distance));
			return list;
		}

		private static ItemDrop? Reachable(MonsterAI ai, Character self, List<Food> foods)
		{
			int num = 0;
			foreach (Food food in foods)
			{
				if (Known(self, food, out var ok))
				{
					if (ok)
					{
						return food.Item;
					}
				}
				else if (num < 3)
				{
					num++;
					if (Check((BaseAI)(object)ai, self, food))
					{
						return food.Item;
					}
				}
			}
			return null;
		}

		private static List<Food> LeftAfterHigher(Character self, List<Food> foods, float range, out bool reserved)
		{
			reserved = false;
			if (foods.Count == 0)
			{
				return foods;
			}
			List<Rival> list = Rivals(self, 2f * range);
			if (list.Count <= 1)
			{
				return foods;
			}
			list.Sort(Higher);
			foreach (Rival item in list)
			{
				if ((Object)(object)item.Animal == (Object)(object)self)
				{
					break;
				}
				Food food = PickFor(item, foods, range);
				if (food != null)
				{
					food.Left--;
					reserved = true;
				}
			}
			if (!reserved)
			{
				return foods;
			}
			return foods.FindAll((Food food2) => food2.Left > 0);
		}

		private static List<Rival> Rivals(Character self, float around)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			List<Rival> list = new List<Rival>();
			ZNetView nview = self.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return list;
			}
			int prefab = nview.GetZDO().GetPrefab();
			string text = null;
			Vector3 position = ((Component)self).transform.position;
			float num = around * around;
			bool flag = false;
			foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
			{
				MonsterAI val = (MonsterAI)(object)((baseAIInstance is MonsterAI) ? baseAIInstance : null);
				if (val == null || (Object)(object)((BaseAI)val).m_character == (Object)null)
				{
					continue;
				}
				Character character = ((BaseAI)val).m_character;
				if ((Object)(object)character == (Object)(object)self)
				{
					flag = true;
					list.Add(Make(character, val));
					continue;
				}
				ZNetView nview2 = ((BaseAI)val).m_nview;
				if ((Object)(object)nview2 == (Object)null || !nview2.IsValid())
				{
					continue;
				}
				ZDO zDO = nview2.GetZDO();
				if (zDO.GetPrefab() != prefab)
				{
					continue;
				}
				Vector3 val2 = ((Component)character).transform.position - position;
				if (!(((Vector3)(ref val2)).sqrMagnitude > num))
				{
					if (text == null)
					{
						text = ((Object)((Component)self).gameObject).name;
					}
					if (!(((Object)((Component)baseAIInstance).gameObject).name != text) && WouldEat(character, val, zDO))
					{
						list.Add(Make(character, val));
					}
				}
			}
			if (!flag)
			{
				BaseAI baseAI = self.GetBaseAI();
				MonsterAI val3 = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
				if (val3 != null)
				{
					list.Add(Make(self, val3));
				}
			}
			return list;
		}

		private static bool WouldEat(Character animal, MonsterAI ai, ZDO zdo)
		{
			if (animal.IsDead() || !animal.IsTamed() || zdo.GetBool(ZDOVars.s_alert, false))
			{
				return false;
			}
			Tameable tamable = ((BaseAI)ai).m_tamable;
			if ((Object)(object)tamable == (Object)null || !tamable.IsHungry())
			{
				return false;
			}
			if (!((Object)(object)tamable.m_saddle == (Object)null))
			{
				return !tamable.m_saddle.HaveValidUser();
			}
			return true;
		}

		private static Rival Make(Character animal, MonsterAI ai)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = animal.m_nview;
			ZDO val = (((Object)(object)nview != (Object)null && nview.IsValid()) ? nview.GetZDO() : null);
			return new Rival
			{
				Animal = animal,
				AI = ai,
				Level = ((val != null) ? val.GetFloat(CareLevelHash, 0f) : 0f),
				Stars = animal.GetLevel(),
				Pregnant = (val != null && val.GetLong(ZDOVars.s_pregnant, 0L) != 0),
				Id = animal.GetZDOID()
			};
		}

		private static int Higher(Rival a, Rival b)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (PregnantLast.Value && a.Pregnant != b.Pregnant)
			{
				if (!a.Pregnant)
				{
					return -1;
				}
				return 1;
			}
			int num = b.Level.CompareTo(a.Level);
			if (num != 0)
			{
				return num;
			}
			int num2 = b.Stars.CompareTo(a.Stars);
			if (num2 == 0)
			{
				return ((ZDOID)(ref a.Id)).CompareTo(b.Id);
			}
			return num2;
		}

		private static Food? PickFor(Rival rival, List<Food> foods, float range)
		{
			//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)
			Vector3 from = ((Component)rival.Animal).transform.position;
			Reach reach = ReachOf(rival.Animal, rival.AI.m_consumeRange);
			List<Food> list = foods.FindAll(delegate(Food food)
			{
				//IL_000a: 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_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				if (food.Left > 0)
				{
					Vector3 val = food.Position - from;
					if (((Vector3)(ref val)).sqrMagnitude <= range * range)
					{
						return reach.Covers(food.Position);
					}
				}
				return false;
			});
			list.Sort(delegate(Food a, Food b)
			{
				//IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = a.Position - from;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				val = b.Position - from;
				return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude);
			});
			int num = 0;
			foreach (Food item in list)
			{
				if (Known(rival.Animal, item, out var ok))
				{
					if (ok)
					{
						return item;
					}
				}
				else if (num < 2)
				{
					num++;
					if (Check((BaseAI)(object)rival.AI, rival.Animal, item))
					{
						return item;
					}
				}
			}
			return null;
		}

		private static long PathKey(Character animal, Food food)
		{
			return ((long)((Object)animal).GetInstanceID() << 32) ^ (uint)((Object)food.Item).GetInstanceID();
		}

		private static bool Known(Character animal, Food food, out bool ok)
		{
			if (Paths.TryGetValue(PathKey(animal, food), out var value) && value.Value > Time.time)
			{
				ok = value.Key;
				return true;
			}
			ok = false;
			return false;
		}

		private static bool Check(BaseAI ai, Character animal, Food food)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ai.HavePath(food.Position);
			Paths[PathKey(animal, food)] = new KeyValuePair<bool, float>(flag, Time.time + 20f);
			return flag;
		}

		private static Reach ReachOf(Character animal, float eatRange)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			ZNetView nview = animal.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return default(Reach);
			}
			ZDO zDO = nview.GetZDO();
			float num = zDO.GetFloat(MaxLengthHash, 0f);
			if (num <= 0f)
			{
				num = 10f;
			}
			if (zDO.GetInt(TiedHash, 0) == 1)
			{
				return new Reach(zDO.GetVec3(PostHash, ((Component)animal).transform.position), num + eatRange);
			}
			long num2 = zDO.GetLong(HolderHash, 0L);
			if (num2 != 0L)
			{
				Player val = PlayerBySession(num2);
				return new Reach(((Object)(object)val != (Object)null) ? ((Component)val).transform.position : ((Component)animal).transform.position, num + eatRange);
			}
			return default(Reach);
		}

		private static Player? PlayerBySession(long session)
		{
			//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)
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null)
				{
					ZDOID zDOID = ((Character)allPlayer).GetZDOID();
					if (((ZDOID)(ref zDOID)).UserID == session)
					{
						return allPlayer;
					}
				}
			}
			return null;
		}

		internal static float LevelOf(Character animal)
		{
			ZNetView nview = animal.m_nview;
			if (!((Object)(object)nview != (Object)null) || !nview.IsValid())
			{
				return 0f;
			}
			return nview.GetZDO().GetFloat(CareLevelHash, 0f);
		}

		private static bool KeepWaiting(Character self)
		{
			float time = Time.time;
			if (!Waiting.TryGetValue(self, out Wait value) || time - value.Last > 25f)
			{
				Dictionary<Character, Wait> waiting = Waiting;
				Wait obj = new Wait
				{
					Since = time
				};
				value = obj;
				waiting[self] = obj;
			}
			value.Last = time;
			return time - value.Since < WaitSeconds.Value;
		}

		internal static void StopWaiting(Character? animal)
		{
			if ((Object)(object)animal != (Object)null)
			{
				Waiting.Remove(animal);
			}
		}

		private static bool IsWaiting(Character animal)
		{
			float time = Time.time;
			if (Waiting.TryGetValue(animal, out Wait value) && time - value.Last <= 25f)
			{
				return time - value.Since < WaitSeconds.Value;
			}
			return false;
		}

		private static void Cleanup()
		{
			float time = Time.time;
			if (time < nextCleanup)
			{
				return;
			}
			nextCleanup = time + 30f;
			List<Character> list = new List<Character>();
			foreach (KeyValuePair<Character, Wait> item in Waiting)
			{
				if ((Object)(object)item.Key == (Object)null || time - item.Value.Last > 100f)
				{
					list.Add(item.Key);
				}
			}
			foreach (Character item2 in list)
			{
				Waiting.Remove(item2);
			}
			list.Clear();
			foreach (KeyValuePair<Character, Shown> rank in Ranks)
			{
				if ((Object)(object)rank.Key == (Object)null || rank.Value.Until < time)
				{
					list.Add(rank.Key);
				}
			}
			foreach (Character item3 in list)
			{
				Ranks.Remove(item3);
			}
			List<long> list2 = new List<long>();
			foreach (KeyValuePair<long, KeyValuePair<bool, float>> path in Paths)
			{
				if (path.Value.Value <= time)
				{
					list2.Add(path.Key);
				}
			}
			foreach (long item4 in list2)
			{
				Paths.Remove(item4);
			}
		}

		private static bool Owned(Procreation procreation)
		{
			if ((Object)(object)procreation.m_nview != (Object)null && procreation.m_nview.IsValid())
			{
				return procreation.m_nview.IsOwner();
			}
			return false;
		}

		internal static bool PregnantBefore(Procreation procreation)
		{
			if (Owned(procreation))
			{
				return procreation.IsPregnant();
			}
			return false;
		}

		internal static void AfterProcreate(Procreation procreation, bool before)
		{
			if (!Owned(procreation))
			{
				return;
			}
			bool flag = procreation.IsPregnant();
			ZDO zDO = procreation.m_nview.GetZDO();
			if (!before && flag)
			{
				Character val = ((Enabled.Value && BestPartner.Value && Plugin.Module.Allowed && GcKern.ModLoaded("tiere")) ? BestMate(procreation, readyOnly: true) : null);
				float num = (((Object)(object)val != (Object)null) ? LevelOf(val) : (-1f));
				if (num >= 0f || zDO.GetFloat(MateLevelHash, -1f) >= 0f)
				{
					zDO.Set(MateLevelHash, num);
				}
			}
			else if (before && !flag && zDO.GetFloat(MateLevelHash, -1f) >= 0f)
			{
				zDO.Set(MateLevelHash, -1f);
			}
		}

		private static Character? BestMate(Procreation procreation, bool readyOnly)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			Character character = procreation.m_character;
			if ((Object)(object)character == (Object)null)
			{
				return null;
			}
			string text = (((Object)(object)procreation.m_seperatePartner != (Object)null) ? ((Object)procreation.m_seperatePartner).name : Utils.GetPrefabName(((Component)procreation).gameObject)) + "(Clone)";
			float num = Mathf.Max(procreation.m_partnerCheckRange, 3f);
			Vector3 position = ((Component)character).transform.position;
			Character result = null;
			float num2 = -1f;
			int num3 = -1;
			float num4 = float.MaxValue;
			foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
			{
				Character val = (((Object)(object)baseAIInstance != (Object)null) ? baseAIInstance.m_character : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)character || val.IsDead() || !val.IsTamed())
				{
					continue;
				}
				float num5 = Vector3.Distance(((Component)val).transform.position, position);
				if (num5 > num || ((Object)((Component)baseAIInstance).gameObject).name != text)
				{
					continue;
				}
				if (readyOnly)
				{
					Procreation component = ((Component)baseAIInstance).GetComponent<Procreation>();
					if (component != null && !component.ReadyForProcreation())
					{
						continue;
					}
				}
				float num6 = LevelOf(val);
				int level = val.GetLevel();
				if (num6 > num2 || (num6 == num2 && (level > num3 || (level == num3 && num5 < num4))))
				{
					result = val;
					num2 = num6;
					num3 = level;
					num4 = num5;
				}
			}
			return result;
		}

		internal static float? MateLevelForBirth(Procreation parent)
		{
			if (!Enabled.Value || !BestPartner.Value || !Plugin.Module.Allowed || (Object)(object)parent.m_nview == (Object)null || !parent.m_nview.IsValid())
			{
				return null;
			}
			float num = parent.m_nview.GetZDO().GetFloat(MateLevelHash, -1f);
			if (num >= 0f)
			{
				return num;
			}
			Character val = BestMate(parent, readyOnly: false);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return LevelOf(val);
		}

		internal static string Hover(Tameable tame, string text)
		{
			Character animal = tame.m_character;
			ZNetView nview = tame.m_nview;
			if (string.IsNullOrEmpty(text) || (Object)(object)animal == (Object)null || (Object)(object)nview == (Object)null || !nview.IsValid() || !tame.IsTamed() || !Enabled.Value || !Plugin.Module.Allowed)
			{
				return text;
			}
			MonsterAI monsterAI = tame.m_monsterAI;
			if (ShowRank.Value && (Object)(object)monsterAI != (Object)null && tame.IsHungry())
			{
				float time = Time.time;
				if (!Ranks.TryGetValue(animal, out Shown value) || value.Until <= time)
				{
					List<Rival> list = Rivals(animal, 2f * monsterAI.m_consumeSearchRange * RangeFactor.Value);
					list.Sort(Higher);
					value = (Ranks[animal] = new Shown
					{
						Until = time + 1f,
						Place = list.FindIndex((Rival rival) => (Object)(object)rival.Animal == (Object)(object)animal) + 1,
						Count = list.Count
					});
				}
				if (value.Count > 1)
				{
					text = text + "\n" + GcLoc.Get("gcff_hover_rank", new object[2] { value.Place, value.Count });
				}
				if (IsWaiting(animal))
				{
					text = text + "\n" + GcLoc.Get("gcff_hover_waiting", Array.Empty<object>());
				}
			}
			ZDO zDO = nview.GetZDO();
			float num = zDO.GetFloat(MateLevelHash, -1f);
			if (num >= 0f && zDO.GetLong(ZDOVars.s_pregnant, 0L) != 0L && GcKern.ModLoaded("tiere"))
			{
				text = text + "\n" + GcLoc.Get("gcff_hover_mate", new object[1] { Mathf.FloorToInt(num) });
			}
			return text;
		}

		internal static void Report(Exception e)
		{
			if (!reported)
			{
				reported = true;
				log.LogWarning((object)$"Futter-Reihenfolge: {e}");
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "FindClosestConsumableItem")]
	internal static class FeedSearchPatch
	{
		private static bool Prefix(MonsterAI __instance, float maxRange, ref ItemDrop? __result)
		{
			try
			{
				if (!FeedOrder.Handles(__instance))
				{
					return true;
				}
				__result = FeedOrder.Find(__instance, maxRange);
				return false;
			}
			catch (Exception e)
			{
				FeedOrder.Report(e);
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "Awake")]
	internal static class FeedStaggerPatch
	{
		private static void Postfix(MonsterAI __instance)
		{
			__instance.m_consumeSearchTimer = Random.Range(0f, __instance.m_consumeSearchInterval);
		}
	}
	[HarmonyPatch(typeof(Tameable), "OnConsumedItem")]
	internal static class FeedEatenPatch
	{
		private static void Postfix(Tameable __instance)
		{
			FeedOrder.StopWaiting(__instance.m_character);
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class FeedMatePatch
	{
		private static void Prefix(Procreation __instance, out bool __state)
		{
			__state = false;
			try
			{
				__state = FeedOrder.PregnantBefore(__instance);
			}
			catch (Exception e)
			{
				FeedOrder.Report(e);
			}
		}

		private static void Postfix(Procreation __instance, bool __state)
		{
			try
			{
				FeedOrder.AfterProcreate(__instance, __state);
			}
			catch (Exception e)
			{
				FeedOrder.Report(e);
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	internal static class FeedHoverPatch
	{
		private static void Postfix(Tameable __instance, ref string __result)
		{
			try
			{
				__result = FeedOrder.Hover(__instance, __result);
			}
			catch (Exception e)
			{
				FeedOrder.Report(e);
			}
		}
	}
	[BepInPlugin("gorduan.gc.futterfolge", "GC_Futterfolge", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			FeedOrder.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Module.TakeOverOldSettings();
			Module.IsOn = () => FeedOrder.Enabled.Value;
			new Harmony("gorduan.gc.futterfolge").PatchAll(typeof(Plugin).Assembly);
			GcHooks.MateLevel = FeedOrder.MateLevelForBirth;
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcff_" + key, Array.Empty<object>())), (string)null).Main("enabled", (ConfigEntryBase)(object)FeedOrder.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("range", (ConfigEntryBase)(object)FeedOrder.RangeFactor, 0.25, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("wait", (ConfigEntryBase)(object)FeedOrder.WaitSeconds, 10.0, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("pregnant", (ConfigEntryBase)(object)FeedOrder.PregnantLast, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("partner", (ConfigEntryBase)(object)FeedOrder.BestPartner, 0.0, "", (Func<bool>)null, "", (Func<bool>)(() => GcKern.ModLoaded("tiere")), (Func<bool>)null)
				.Sub("wild", (ConfigEntryBase)(object)FeedOrder.Wild, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("rank", (ConfigEntryBase)(object)FeedOrder.ShowRank, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}
	}
	internal static class GcMod
	{
		public const string Id = "futterfolge";

		public const string Guid = "gorduan.gc.futterfolge";

		public const string Name = "GC_Futterfolge";

		public const string Version = "1.8.1";

		public const int Stufe = 4;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "futterfolge";
				val.Guid = "gorduan.gc.futterfolge";
				val.Name = "GC_Futterfolge";
				val.Version = "1.8.1";
				val.Stufe = 4;
				val.Seite = (GcSeite)2;
				val.Braucht = Array.Empty<string>();
				val.Partner = new string[1] { "tiere" };
				val.Fremd = Array.Empty<string>();
				val.AlteConfig = "";
				val.Ausgleich = 1f;
				return val;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Kern.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Kern;
using GC.Kern.ModCheck;
using GC.Kern.Progression;
using GC.Shared;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Kern")]
[assembly: AssemblyTitle("GC_Kern")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Kern
{
	[HarmonyPatch(typeof(Localization), "SetLanguage")]
	internal static class LanguageKeepPatch
	{
		private static void Prefix(Localization __instance, out Dictionary<string, string>? __state)
		{
			__state = ((__instance.m_translations != null) ? new Dictionary<string, string>(__instance.m_translations) : null);
		}

		private static void Postfix(Localization __instance, Dictionary<string, string>? __state)
		{
			if (__state == null || __instance.m_translations == null)
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<string, string> item in __state)
			{
				if (!__instance.m_translations.ContainsKey(item.Key))
				{
					__instance.m_translations[item.Key] = item.Value;
					num++;
				}
			}
			if (num > 0)
			{
				__instance.m_cache.EvictAll();
				KernPlugin.Log.LogInfo((object)$"Sprachwechsel: {num} Texte anderer Mods wiederhergestellt.");
			}
		}
	}
	internal static class ModSwitch
	{
		internal enum State
		{
			Loaded,
			Failed,
			Off,
			OtherProcess,
			NotLoaded
		}

		internal sealed class Mod
		{
			public string Guid = "";

			public string Name = "";

			public string Version = "";

			public string Location = "";

			public string Package = "";

			public string PackageVersion = "";

			public string Namespace = "";

			public string PackageName = "";

			public State State;

			public string Reason = "";

			public string[] HardDeps = Array.Empty<string>();

			public bool Protected;

			public string Search = "";
		}

		internal sealed class Profile
		{
			public string Name = "";

			public string File = "";

			public HashSet<string> Off = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		[Serializable]
		private sealed class ManifestJson
		{
			public string name = "";

			public string version_number = "";
		}

		private const string DataAll = "GC.ModSchalter.All";

		private const string DataSkipped = "GC.ModSchalter.Skipped";

		private const string DataProtected = "GC.ModSchalter.Protected";

		private const string DataFile = "GC.ModSchalter.File";

		private const string KernGuid = "gorduan.gc.kern";

		private static List<Mod>? catalog;

		private static HashSet<string>? wanted;

		private static HashSet<string> skippedAtStart = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static bool PatcherActive => AppDomain.CurrentDomain.GetData("GC.ModSchalter.File") is string;

		internal static string Folder => Path.Combine(Paths.ConfigPath, "GC_Kern");

		private static string ListFile => (AppDomain.CurrentDomain.GetData("GC.ModSchalter.File") as string) ?? Path.Combine(Folder, "aus.txt");

		private static string ProfileFolder => Path.Combine(Folder, "profile");

		internal static IReadOnlyList<Mod> Catalog => catalog ?? (catalog = BuildCatalog());

		private static HashSet<string> Wanted => wanted ?? (wanted = ReadList(ListFile));

		internal static bool RestartNeeded
		{
			get
			{
				if (!PatcherActive)
				{
					return false;
				}
				HashSet<string> hashSet = new HashSet<string>(from m in Catalog
					where !m.Protected
					select m.Guid, StringComparer.OrdinalIgnoreCase);
				hashSet.IntersectWith(Wanted);
				return !hashSet.SetEquals(skippedAtStart);
			}
		}

		internal static string LastError { get; private set; } = "";

		internal static bool IsWantedOff(Mod mod)
		{
			if (!mod.Protected)
			{
				return Wanted.Contains(mod.Guid);
			}
			return false;
		}

		internal static Mod? Find(string guid)
		{
			return Catalog.FirstOrDefault((Mod m) => string.Equals(m.Guid, guid, StringComparison.OrdinalIgnoreCase));
		}

		private static List<Mod> BuildCatalog()
		{
			ImportModMenu();
			AppDomain currentDomain = AppDomain.CurrentDomain;
			List<PluginInfo> list = (currentDomain.GetData("GC.ModSchalter.All") as List<PluginInfo>) ?? new List<PluginInfo>();
			List<PluginInfo> list2 = (currentDomain.GetData("GC.ModSchalter.Skipped") as List<PluginInfo>) ?? new List<PluginInfo>();
			skippedAtStart = new HashSet<string>(list2.Select((PluginInfo info) => info.Metadata.GUID), StringComparer.OrdinalIgnoreCase);
			Dictionary<string, Mod> byGuid = new Dictionary<string, Mod>(StringComparer.OrdinalIgnoreCase);
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				Add(value, (!((Object)(object)value.Instance != (Object)null)) ? State.Failed : State.Loaded, "");
			}
			foreach (PluginInfo item in list2)
			{
				Add(item, State.Off, "");
			}
			foreach (PluginInfo item2 in list)
			{
				if (!byGuid.ContainsKey(item2.Metadata.GUID))
				{
					var (state, reason) = NotLoaded(item2);
					Add(item2, state, reason);
				}
			}
			HashSet<string> hashSet = new HashSet<string>((currentDomain.GetData("GC.ModSchalter.Protected") as string[]) ?? Array.Empty<string>(), StringComparer.OrdinalIgnoreCase);
			if (hashSet.Count == 0)
			{
				hashSet = Protected(byGuid);
			}
			foreach (Mod value2 in byGuid.Values)
			{
				value2.Protected = hashSet.Contains(value2.Guid);
			}
			return byGuid.Values.OrderBy<Mod, string>((Mod m) => m.Name, StringComparer.OrdinalIgnoreCase).ToList();
			void Add(PluginInfo info, State state2, string reason2)
			{
				string gUID = info.Metadata.GUID;
				if (!byGuid.ContainsKey(gUID))
				{
					Mod mod = new Mod
					{
						Guid = gUID,
						Name = info.Metadata.Name,
						Version = info.Metadata.Version.ToString(),
						Location = (info.Location ?? ""),
						State = state2,
						Reason = reason2,
						HardDeps = (from d in info.Dependencies
							where (d.Flags & 1) > 0
							select d.DependencyGUID).ToArray()
					};
					FindPackage(mod);
					mod.Search = string.Join(" ", mod.Name, mod.Guid, mod.Package).ToLowerInvariant();
					byGuid[gUID] = mod;
				}
			}
		}

		private static (State, string) NotLoaded(PluginInfo info)
		{
			string[] array = info.Processes.Select((BepInProcess p) => p.ProcessName).ToArray();
			if (array.Length != 0 && !array.Any((string p) => string.Equals(Path.GetFileNameWithoutExtension(p), Paths.ProcessName, StringComparison.OrdinalIgnoreCase)))
			{
				return (State.OtherProcess, string.Join(", ", array));
			}
			string text = Chainloader.DependencyErrors.FirstOrDefault((string line) => line.Contains(info.Metadata.GUID) || line.Contains("[" + info.Metadata.Name));
			if (text == null)
			{
				return (State.NotLoaded, "");
			}
			return (State.Failed, text);
		}

		private static HashSet<string> Protected(Dictionary<string, Mod> byGuid)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "gorduan.gc.kern" };
			Queue<string> queue = new Queue<string>(hashSet);
			while (queue.Count > 0)
			{
				if (!byGuid.TryGetValue(queue.Dequeue(), out Mod value))
				{
					continue;
				}
				string[] hardDeps = value.HardDeps;
				foreach (string item in hardDeps)
				{
					if (hashSet.Add(item))
					{
						queue.Enqueue(item);
					}
				}
			}
			return hashSet;
		}

		private static void FindPackage(Mod mod)
		{
			try
			{
				string text = Path.GetFullPath(Paths.PluginPath).TrimEnd('\\', '/');
				string text2 = ((mod.Location.Length > 0) ? Path.GetDirectoryName(Path.GetFullPath(mod.Location)) : null);
				while (text2 != null && text2.Length > text.Length && text2.StartsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					string path = Path.Combine(text2, "manifest.json");
					if (File.Exists(path))
					{
						ManifestJson manifestJson = JsonUtility.FromJson<ManifestJson>(File.ReadAllText(path));
						mod.Package = Path.GetFileName(text2);
						mod.PackageName = manifestJson?.name ?? "";
						mod.PackageVersion = manifestJson?.version_number ?? "";
						int num = mod.Package.IndexOf('-');
						if (num > 0 && string.Equals(mod.Package.Substring(num + 1), mod.PackageName, StringComparison.OrdinalIgnoreCase))
						{
							mod.Namespace = mod.Package.Substring(0, num);
						}
						break;
					}
					text2 = Path.GetDirectoryName(text2);
				}
			}
			catch
			{
			}
		}

		internal static List<Mod> SetOff(Mod start, bool off)
		{
			List<Mod> list = new List<Mod>();
			if (!PatcherActive || start.Protected)
			{
				return list;
			}
			Queue<Mod> queue = new Queue<Mod>();
			queue.Enqueue(start);
			while (queue.Count > 0)
			{
				Mod mod = queue.Dequeue();
				if (mod.Protected || Wanted.Contains(mod.Guid) == off)
				{
					continue;
				}
				if (off)
				{
					Wanted.Add(mod.Guid);
				}
				else
				{
					Wanted.Remove(mod.Guid);
				}
				list.Add(mod);
				IEnumerable<Mod> enumerable2;
				if (!off)
				{
					IEnumerable<Mod> enumerable = (from other in mod.HardDeps.Select(Find)
						where other != null
						select other).Cast<Mod>();
					enumerable2 = enumerable;
				}
				else
				{
					enumerable2 = Catalog.Where((Mod other) => other.HardDeps.Contains<string>(mod.Guid, StringComparer.OrdinalIgnoreCase));
				}
				foreach (Mod item in enumerable2)
				{
					queue.Enqueue(item);
				}
			}
			if (!Save())
			{
				list.Clear();
			}
			return list;
		}

		internal static void AllOn()
		{
			Wanted.Clear();
			Save();
		}

		private static HashSet<string> WithDependents(IEnumerable<string> off)
		{
			HashSet<string> hashSet = new HashSet<string>(off, StringComparer.OrdinalIgnoreCase);
			bool flag = true;
			while (flag)
			{
				flag = false;
				foreach (Mod item in Catalog)
				{
					if (!item.Protected && !hashSet.Contains(item.Guid) && item.HardDeps.Any(hashSet.Contains))
					{
						hashSet.Add(item.Guid);
						flag = true;
					}
				}
			}
			return hashSet;
		}

		internal static List<Mod> Dependents(Mod mod)
		{
			return Catalog.Where((Mod other) => !IsWantedOff(other) && other.HardDeps.Contains<string>(mod.Guid, StringComparer.OrdinalIgnoreCase)).ToList();
		}

		internal static List<string> MissingDeps(Mod mod)
		{
			return (from guid in mod.HardDeps.Where(delegate(string guid)
				{
					Mod mod2 = Find(guid);
					return mod2 == null || IsWantedOff(mod2);
				})
				select Find(guid)?.Name ?? guid).ToList();
		}

		private static bool Save()
		{
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(ListFile));
				List<string> list = new List<string> { "# Im Menü GC Option ausgeschaltete Mods, eine GUID je Zeile. Datei löschen = alle wieder an." };
				list.AddRange(Wanted.OrderBy<string, string>((string g) => g, StringComparer.OrdinalIgnoreCase));
				File.WriteAllLines(ListFile, list, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				LastError = "";
				return true;
			}
			catch (Exception ex)
			{
				LastError = ex.Message;
				wanted = ReadList(ListFile);
				return false;
			}
		}

		private static HashSet<string> ReadList(string file)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			try
			{
				if (File.Exists(file))
				{
					string[] array = File.ReadAllLines(file);
					for (int i = 0; i < array.Length; i++)
					{
						string text = array[i].Trim();
						if (text.Length > 0 && !text.StartsWith("#", StringComparison.Ordinal))
						{
							hashSet.Add(text);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("GC_Kern: " + file + " nicht lesbar: " + ex.Message));
			}
			return hashSet;
		}

		internal static List<Profile> Profiles()
		{
			List<Profile> list = new List<Profile>();
			if (!Directory.Exists(ProfileFolder))
			{
				return list;
			}
			foreach (string item in Directory.GetFiles(ProfileFolder, "*.txt").OrderBy<string, string>((string f) => f, StringComparer.OrdinalIgnoreCase))
			{
				list.Add(new Profile
				{
					Name = Path.GetFileNameWithoutExtension(item),
					File = item,
					Off = ReadList(item)
				});
			}
			return list;
		}

		private static HashSet<string> Known(IEnumerable<string> guids)
		{
			HashSet<string> hashSet = new HashSet<string>(from m in Catalog
				where !m.Protected
				select m.Guid, StringComparer.OrdinalIgnoreCase);
			hashSet.IntersectWith(guids);
			return hashSet;
		}

		internal static bool IsCurrent(Profile profile)
		{
			return Known(profile.Off).SetEquals(Known(Wanted));
		}

		internal static int MissingIn(Profile profile)
		{
			return profile.Off.Count((string guid) => Find(guid) == null);
		}

		internal static string CleanName(string name)
		{
			return new string((from c in name.Trim()
				where Array.IndexOf(Path.GetInvalidFileNameChars(), c) < 0
				select c).ToArray()).Trim().TrimEnd('.');
		}

		internal static bool SaveProfile(string name)
		{
			return WriteProfile(name, Wanted);
		}

		internal static bool WriteProfile(string name, IEnumerable<string> off)
		{
			string text = CleanName(name);
			if (text.Length == 0)
			{
				return false;
			}
			try
			{
				Directory.CreateDirectory(ProfileFolder);
				List<string> list = new List<string> { "# GC Option, Mod-Profil „" + text + "“: diese Mods aus, alle anderen an." };
				list.AddRange(off.OrderBy<string, string>((string g) => g, StringComparer.OrdinalIgnoreCase));
				File.WriteAllLines(Path.Combine(ProfileFolder, text + ".txt"), list, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				LastError = "";
				return true;
			}
			catch (Exception ex)
			{
				LastError = ex.Message;
				return false;
			}
		}

		internal static string FreeName(string name)
		{
			HashSet<string> hashSet = new HashSet<string>(from p in Profiles()
				select p.Name, StringComparer.OrdinalIgnoreCase);
			string text = CleanName(name);
			string text2 = text;
			int num = 2;
			while (hashSet.Contains(text2))
			{
				text2 = $"{text} ({num})";
				num++;
			}
			return text2;
		}

		internal static int ApplyProfile(Profile profile)
		{
			HashSet<string> hashSet = new HashSet<string>(Wanted, StringComparer.OrdinalIgnoreCase);
			Wanted.Clear();
			Wanted.UnionWith(WithDependents(Known(profile.Off)));
			if (!Save())
			{
				wanted = hashSet;
				return -1;
			}
			return MissingIn(profile);
		}

		internal static bool DeleteProfile(Profile profile)
		{
			try
			{
				string text = Path.Combine(ProfileFolder, "geloescht");
				Directory.CreateDirectory(text);
				string destFileName = Path.Combine(text, Path.GetFileNameWithoutExtension(profile.File) + "-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".txt");
				File.Move(profile.File, destFileName);
				LastError = "";
				return true;
			}
			catch (Exception ex)
			{
				LastError = ex.Message;
				return false;
			}
		}

		internal static string ProfileText(Profile profile)
		{
			return "# GC Option, Mod-Profil „" + profile.Name + "“\n" + string.Join("\n", profile.Off.OrderBy<string, string>((string g) => g, StringComparer.OrdinalIgnoreCase)) + "\n";
		}

		internal static HashSet<string> ParseGuids(string text)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = text.Replace("\r", "").Split('\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length > 0 && !text2.StartsWith("#", StringComparison.Ordinal) && text2.IndexOf(' ') < 0)
				{
					hashSet.Add(text2);
				}
			}
			return hashSet;
		}

		private static void ImportModMenu()
		{
			try
			{
				string text = Path.Combine(Paths.ConfigPath, "ModMenu");
				if (!Directory.Exists(text))
				{
					return;
				}
				string text2 = Path.Combine(text, "disabled.txt");
				if (File.Exists(text2) && !File.Exists(ListFile))
				{
					Directory.CreateDirectory(Path.GetDirectoryName(ListFile));
					File.Copy(text2, ListFile);
					Debug.Log((object)"GC_Kern: ausgeschaltete Mods aus Mod Menu übernommen.");
				}
				string path = Path.Combine(text, "profiles");
				if (Directory.Exists(path) && !Directory.Exists(ProfileFolder))
				{
					Directory.CreateDirectory(ProfileFolder);
					string[] files = Directory.GetFiles(path, "*.txt");
					foreach (string text3 in files)
					{
						File.Copy(text3, Path.Combine(ProfileFolder, Path.GetFileName(text3)));
					}
					Debug.Log((object)"GC_Kern: Profile aus Mod Menu übernommen.");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("GC_Kern: Mod Menu nicht übernommen: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Awake")]
	internal static class RagdollScalePatch
	{
		private static void Postfix(Ragdoll __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				float num = component.GetZDO().GetFloat(GcKeys.RagdollScaleHash, 0f);
				if (num > 0f)
				{
					((Component)__instance).transform.localScale = Vector3.one * num;
				}
			}
		}
	}
	internal static class VPlusOptions
	{
		private static ConfigFile? config;

		private static GcMenu? menu;

		private static bool dirty;

		private static MethodInfo? reapply;

		private static PropertyInfo? readyForEdit;

		internal static void Register(GcMenu gcMenu)
		{
			if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.valheim_plus", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			menu = gcMenu;
			config = value.Instance.Config;
			reapply = AccessTools.Method(AccessTools.TypeByName("ValheimPlus.Configurations.BepInExConfig"), "ReapplyPatches", new Type[1] { typeof(string) }, (Type[])null);
			readyForEdit = AccessTools.Property(AccessTools.TypeByName("ValheimPlus.Configurations.ConfigurationManagerWatcher"), "ReadyForEdit");
			if (reapply == null)
			{
				KernPlugin.Log.LogWarning((object)"ValheimPlus: BepInExConfig.ReapplyPatches nicht gefunden. Änderungen im Menü wirken erst nach dem nächsten Start.");
			}
			config.SettingChanged += delegate(object _, SettingChangedEventArgs e)
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					dirty = true;
				}
				object obj;
				if (e == null)
				{
					obj = null;
				}
				else
				{
					ConfigEntryBase changedSetting = e.ChangedSetting;
					obj = ((changedSetting != null) ? changedSetting.Definition.Key : null);
				}
				if ((string?)obj == "enabled")
				{
					Build();
				}
			};
			Build();
			gcMenu.Closed += OnClosed;
		}

		private static void Build()
		{
			if (config == null || menu == null)
			{
				return;
			}
			GcMenuSection gcMenuSection = menu.Section("gc_vplus", 60, (string key) => GcLoc.Get("gck_vplus_" + key), "");
			int num = 0;
			int num2 = 0;
			foreach (IGrouping<string, ConfigDefinition> item in (from d in config.Keys
				group d by d.Section).OrderBy<IGrouping<string, ConfigDefinition>, string>((IGrouping<string, ConfigDefinition> g) => g.Key, StringComparer.OrdinalIgnoreCase))
			{
				List<ConfigEntryBase> list = item.Select((ConfigDefinition d) => config[d]).Where(Supported).ToList();
				if (list.Count == 0)
				{
					continue;
				}
				Dictionary<string, string> descriptions = list.ToDictionary<ConfigEntryBase, string, string>((ConfigEntryBase e) => e.Definition.Key, delegate(ConfigEntryBase e)
				{
					ConfigDescription description = e.Description;
					return ((description != null) ? description.Description : null) ?? "";
				}, StringComparer.Ordinal);
				string title = item.Key;
				GcMenuGroup gcMenuGroup = gcMenuSection.Group("vplus_" + item.Key, () => title, (string key) => Text(key, descriptions), "");
				ConfigEntryBase enabled = ((IEnumerable<ConfigEntryBase>)list).FirstOrDefault((Func<ConfigEntryBase, bool>)((ConfigEntryBase e) => e.Definition.Key == "enabled" && e.SettingType == typeof(bool)));
				if (enabled != null)
				{
					gcMenuGroup.Main("enabled", enabled, null, "", null, 0.0, "", () => (Object)(object)ZNet.instance == (Object)null || IsOn(enabled), Locked);
					num2++;
					if (!IsOn(enabled))
					{
						num++;
						continue;
					}
				}
				foreach (ConfigEntryBase item2 in list)
				{
					if (item2 != enabled)
					{
						if (enabled != null)
						{
							gcMenuGroup.Sub(item2.Definition.Key, item2, 0.0, "", null, "", null, Locked);
						}
						else
						{
							gcMenuGroup.Main(item2.Definition.Key, item2, null, "", null, 0.0, "", null, Locked);
						}
						num2++;
					}
				}
				num++;
			}
			KernPlugin.Log.LogDebug((object)$"ValheimPlus im Menü GC Option: {num} Abschnitte, {num2} Zeilen.");
		}

		private static bool IsOn(ConfigEntryBase entry)
		{
			object boxedValue = entry.BoxedValue;
			bool flag = default(bool);
			int num;
			if (boxedValue is bool)
			{
				flag = (bool)boxedValue;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static bool Locked()
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return true;
			}
			try
			{
				return readyForEdit != null && readyForEdit.GetValue(null, null) is bool flag && !flag;
			}
			catch
			{
				return false;
			}
		}

		private static bool Supported(ConfigEntryBase entry)
		{
			Type settingType = entry.SettingType;
			if (settingType.IsEnum)
			{
				return !settingType.IsDefined(typeof(FlagsAttribute), inherit: false);
			}
			if (!(settingType == typeof(bool)) && !(settingType == typeof(int)) && !(settingType == typeof(float)) && !(settingType == typeof(KeyboardShortcut)))
			{
				return settingType == typeof(KeyCode);
			}
			return true;
		}

		private static string Text(string key, Dictionary<string, string> descriptions)
		{
			if (key.StartsWith("t_", StringComparison.Ordinal) && key.EndsWith("_name", StringComparison.Ordinal))
			{
				return key.Substring(2, key.Length - 7);
			}
			if (key.StartsWith("t_", StringComparison.Ordinal) && key.EndsWith("_desc", StringComparison.Ordinal))
			{
				string key2 = key.Substring(2, key.Length - 7);
				if (!descriptions.TryGetValue(key2, out string value))
				{
					return "";
				}
				return FirstSentences(value);
			}
			if (key.StartsWith("enum_", StringComparison.Ordinal))
			{
				return key.Substring(5);
			}
			return key;
		}

		private static string FirstSentences(string text)
		{
			string text2 = text.Replace("\r", " ").Replace("\n", " ").Trim();
			int num = -1;
			int i = 0;
			int num2 = 0;
			for (; i < text2.Length; i++)
			{
				if (text2[i] == '.' && (i + 1 == text2.Length || text2[i + 1] == ' ') && ++num2 == 2)
				{
					num = i + 1;
					break;
				}
			}
			if (num <= 0)
			{
				return text2;
			}
			return text2.Substring(0, num);
		}

		private static void OnClosed()
		{
			if (!dirty || (Object)(object)ZNet.instance != (Object)null)
			{
				return;
			}
			dirty = false;
			try
			{
				reapply?.Invoke(null, new object[1] { "Einstellungen in GC Option geändert" });
			}
			catch (Exception ex)
			{
				KernPlugin.Log.LogWarning((object)("ValheimPlus konnte die Änderungen nicht neu anwenden: " + ex.Message));
			}
		}
	}
}
namespace GC.Kern.ModCheck
{
	internal static class Plugin
	{
		public const string Guid = "gorduan.gc_modcheck";

		public const string ModName = "GC_ModCheck";

		public const string Version = "1.0.0";

		internal const string Rpc = "GC_Kern_ServerInfo_v1";

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<bool> ShowOnFailure = null;

		internal static ConfigEntry<bool> ShowOnJoinIfMissing = null;

		internal static ConfigEntry<string> HiddenOnServer = null;

		internal static ConfigEntry<string> IgnoreClientOnly = null;

		internal static List<ModInfo>? ServerMods;

		internal static Report? LastReport;

		internal static HashSet<string> OptionalOnServer = new HashSet<string>(StringComparer.Ordinal);

		internal static bool Blocked => Chainloader.PluginInfos.ContainsKey("gorduan.gc_modcheck");

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return !Blocked;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile Config)
		{
			Log = KernPlugin.Log;
			Enabled = Gc.Bind(Config, "5 - ModCheck", "Enabled", value: true, "Funktion ein- oder ausschalten (auch im Menü GC Option).");
			ShowOnFailure = Gc.Bind(Config, "5 - ModCheck", "ShowOnFailedConnection", value: true, "Nach einer fehlgeschlagenen Verbindung das Vergleichsfenster im Hauptmenü zeigen.");
			ShowOnJoinIfMissing = Gc.Bind(Config, "5 - ModCheck", "ShowOnJoinIfMissing", value: true, "Nach erfolgreichem Beitritt das Fenster zeigen, wenn dir Mods des Servers fehlen.");
			HiddenOnServer = Gc.Bind(Config, "5 - ModCheck - Server", "HiddenGuids", "", "Nur Server: kommagetrennte Plugin-GUIDs, die nicht an Spieler gemeldet werden (reine Server-Mods).");
			IgnoreClientOnly = Gc.Bind(Config, "5 - ModCheck - Client", "ClientOnlyGuids", "", "Kommagetrennte GUIDs eigener Client-Mods, die nicht als 'nur bei dir' gelistet werden.");
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ConsoleCommand());
		}

		internal static List<ModInfo> LocalMods()
		{
			List<ModInfo> list = new List<ModInfo>();
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				string package = "";
				try
				{
					string directoryName = Path.GetDirectoryName(value.Location);
					string text = ((directoryName != null) ? Path.GetFileName(directoryName) : null);
					if (text != null && !text.Equals("plugins", StringComparison.OrdinalIgnoreCase))
					{
						package = text;
					}
				}
				catch
				{
				}
				list.Add(new ModInfo(value.Metadata.GUID, value.Metadata.Name, value.Metadata.Version.ToString(), package));
			}
			return list.OrderBy<ModInfo, string>((ModInfo mod) => mod.Name, StringComparer.OrdinalIgnoreCase).ToList();
		}

		internal static ZPackage BuildPackage()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			HashSet<string> hidden = Gc.ParseList(HiddenOnServer.Value);
			List<ModInfo> list = (from mod in LocalMods()
				where IsGc(mod.Guid) || (On && !hidden.Contains(mod.Guid))
				select mod).ToList();
			ZPackage val = new ZPackage();
			val.Write(list.Count);
			foreach (ModInfo item in list)
			{
				val.Write(item.Guid);
				val.Write(item.Name);
				val.Write(item.Version);
				val.Write(item.Package);
			}
			val.Write(Math.Max(1, GcKern.HighestLocalStufe));
			val.Write(On);
			val.Write(GcKern.Modules.Count);
			foreach (GcModule module in GcKern.Modules)
			{
				val.Write(module.Info.Guid);
				val.Write((int)module.Info.Seite);
			}
			return val;
		}

		internal static bool IsGc(string guid)
		{
			if (!(guid == "gorduan.gc.kern"))
			{
				return guid.StartsWith("gorduan.gc.", StringComparison.Ordinal);
			}
			return true;
		}

		internal static void Receive(ZPackage pkg)
		{
			List<ModInfo> list = new List<ModInfo>();
			int num = pkg.ReadInt();
			for (int i = 0; i < num; i++)
			{
				list.Add(new ModInfo(pkg.ReadString(), pkg.ReadString(), pkg.ReadString(), pkg.ReadString()));
			}
			int num2 = 5;
			bool flag = true;
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			try
			{
				num2 = pkg.ReadInt();
				flag = pkg.ReadBool();
				int num3 = pkg.ReadInt();
				for (int j = 0; j < num3; j++)
				{
					string item = pkg.ReadString();
					if (pkg.ReadInt() == 0)
					{
						hashSet.Add(item);
					}
				}
			}
			catch
			{
			}
			OptionalOnServer = hashSet;
			GcServerInfo gcServerInfo = new GcServerInfo
			{
				Stufe = num2
			};
			foreach (ModInfo item2 in list)
			{
				gcServerInfo.Guids.Add(item2.Guid);
			}
			GcKern.Server = gcServerInfo;
			Log.LogInfo((object)$"Server: {list.Count} Mods, Stufe {num2} ({GcKern.StufeName(num2)}).");
			ServerMods = list;
			if (!On || !flag)
			{
				return;
			}
			HashSet<string> ignoreClientOnly = Gc.ParseList(IgnoreClientOnly.Value);
			LastReport = Report.Create(list, LocalMods(), ignoreClientOnly, hashSet);
			Log.LogInfo((object)$"Server meldet {list.Count} Mods. Fehlend: {LastReport.Missing.Count}, andere Version: {LastReport.Different.Count}, nur hier: {LastReport.ClientOnly.Count}.");
			string[] array = LastReport.ToText().Split('\n');
			foreach (string text in array)
			{
				if (text.Trim().Length > 0)
				{
					Log.LogInfo((object)text);
				}
			}
		}
	}
	internal sealed class ModInfo
	{
		public string Guid { get; }

		public string Name { get; }

		public string Version { get; }

		public string Package { get; }

		public ModInfo(string guid, string name, string version, string package)
		{
			Guid = guid;
			Name = name;
			Version = version;
			Package = package;
		}

		public string Describe()
		{
			if (Package.Length <= 0)
			{
				return Name + " " + Version + "  (" + Guid + ")";
			}
			return Name + " " + Version + "  [" + Package + "]";
		}
	}
	internal sealed class Report
	{
		public List<ModInfo> Missing = new List<ModInfo>();

		public List<(ModInfo Server, ModInfo Client)> Different = new List<(ModInfo, ModInfo)>();

		public List<ModInfo> ClientOnly = new List<ModInfo>();

		public bool HasProblems
		{
			get
			{
				if (Missing.Count <= 0)
				{
					return Different.Count > 0;
				}
				return true;
			}
		}

		public static Report Create(List<ModInfo> server, List<ModInfo> client, HashSet<string> ignoreClientOnly, HashSet<string> optional)
		{
			Report report = new Report();
			Dictionary<string, ModInfo> dictionary = (from mod in client
				group mod by mod.Guid).ToDictionary((IGrouping<string, ModInfo> group) => group.Key, (IGrouping<string, ModInfo> group) => group.First());
			Dictionary<string, ModInfo> dictionary2 = (from mod in server
				group mod by mod.Guid).ToDictionary((IGrouping<string, ModInfo> group) => group.Key, (IGrouping<string, ModInfo> group) => group.First());
			foreach (ModInfo item in server)
			{
				if (!optional.Contains(item.Guid))
				{
					if (!dictionary.TryGetValue(item.Guid, out var value))
					{
						report.Missing.Add(item);
					}
					else if (value.Version != item.Version)
					{
						report.Different.Add((item, value));
					}
				}
			}
			foreach (ModInfo item2 in client)
			{
				if (!dictionary2.ContainsKey(item2.Guid) && !ignoreClientOnly.Contains(item2.Guid))
				{
					report.ClientOnly.Add(item2);
				}
			}
			return report;
		}

		public string ToText()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(GcLoc.Get("gcm_title"));
			stringBuilder.AppendLine();
			stringBuilder.AppendLine(GcLoc.Get("gcm_missing", Missing.Count));
			foreach (ModInfo item in Missing)
			{
				stringBuilder.AppendLine("- " + item.Describe());
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine(GcLoc.Get("gcm_different", Different.Count));
			foreach (var (modInfo, modInfo2) in Different)
			{
				stringBuilder.AppendLine("- " + GcLoc.Get("gcm_version_line", modInfo.Name, modInfo.Version, modInfo2.Version) + ((modInfo.Package.Length > 0) ? ("  [" + modInfo.Package + "]") : ""));
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine(GcLoc.Get("gcm_client_only", ClientOnly.Count));
			foreach (ModInfo item2 in ClientOnly)
			{
				stringBuilder.AppendLine("- " + item2.Describe());
			}
			return stringBuilder.ToString();
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	internal static class NewConnectionPatch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			peer.m_rpc.Register<ZPackage>("GC_Kern_ServerInfo_v1", (Action<ZRpc, ZPackage>)delegate(ZRpc _, ZPackage pkg)
			{
				if (!ZNet.instance.IsServer())
				{
					Plugin.Receive(pkg);
				}
			});
			if (__instance.IsServer())
			{
				peer.m_rpc.Invoke("GC_Kern_ServerInfo_v1", new object[1] { Plugin.BuildPackage() });
			}
			else
			{
				Plugin.ServerMods = null;
				Plugin.LastReport = null;
				GcKern.Server = null;
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnDestroy")]
	internal static class ServerInfoResetPatch
	{
		private static void Postfix()
		{
			GcKern.Server = null;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
	internal static class ConnectErrorPatch
	{
		private static void Postfix()
		{
			if (Plugin.On && Plugin.ShowOnFailure.Value && Plugin.LastReport != null)
			{
				ReportWindow.Show(Plugin.LastReport);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class SpawnPatch
	{
		private static bool shown;

		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !shown && Plugin.On && Plugin.ShowOnJoinIfMissing.Value && Plugin.LastReport != null && Plugin.LastReport.Missing.Count > 0)
			{
				shown = true;
				ReportWindow.Show(Plugin.LastReport);
			}
		}
	}
	internal class ConsoleCommand : ConsoleCommand
	{
		public override string Name => "modcheck";

		public override string Help => "GC_Kern: Mod-Abgleich mit dem Server anzeigen";

		public override void Run(string[] args)
		{
			if (Plugin.LastReport == null)
			{
				Console.instance.Print("Keine Serverliste empfangen (Server ohne GC_Kern, Mod-Abgleich aus oder nicht verbunden).");
			}
			else
			{
				ReportWindow.Show(Plugin.LastReport);
			}
		}
	}
	internal static class ReportWindow
	{
		private static GameObject? window;

		private static Text? header;

		private static Text? body;

		private static string text = "";

		public static void Show(Report report)
		{
			if (!Gc.IsHeadless && GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				Build();
				text = report.ToText();
				header.text = GcLoc.Get(report.HasProblems ? "gcm_header_problems" : "gcm_header_ok");
				body.text = Colorize(report);
				window.SetActive(true);
				window.transform.SetAsLastSibling();
				GUIManager.BlockInput(true);
			}
		}

		private static string Colorize(Report report)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("<color=#ff8866><b>" + GcLoc.Get("gcm_missing", report.Missing.Count) + "</b></color>");
			foreach (ModInfo item in report.Missing)
			{
				stringBuilder.AppendLine("  • " + item.Describe());
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<color=#ffd166><b>" + GcLoc.Get("gcm_different", report.Different.Count) + "</b></color>");
			foreach (var (modInfo, modInfo2) in report.Different)
			{
				stringBuilder.AppendLine("  • " + GcLoc.Get("gcm_version_line", modInfo.Name, modInfo.Version, modInfo2.Version));
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<color=#9fd3ff><b>" + GcLoc.Get("gcm_client_only", report.ClientOnly.Count) + "</b></color>");
			foreach (ModInfo item2 in report.ClientOnly)
			{
				stringBuilder.AppendLine("  • " + item2.Describe());
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<i>" + GcLoc.Get("gcm_note") + "</i>");
			return stringBuilder.ToString();
		}

		private static void Build()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0157: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window != (Object)null)
			{
				return;
			}
			window = GcUi.CreateWindow("GC_ModCheck_Window", 900f, 620f, out header, out RectTransform inner);
			RectTransform val = GcUi.CreateScroll((Transform)(object)inner, 820f, 440f);
			body = GUIManager.Instance.CreateText("", (Transform)(object)val, new Vector2(0f, 1f), new Vector2(1f, 1f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 18, Color.white, true, Color.black, 780f, 0f, true).GetComponent<Text>();
			body.supportRichText = true;
			body.horizontalOverflow = (HorizontalWrapMode)0;
			body.verticalOverflow = (VerticalWrapMode)1;
			GcUi.CreateButton(window.transform, GcLoc.Get("gcm_copy"), new Vector2(0.5f, 0f), new Vector2(-130f, 44f), 240f, 44f, delegate
			{
				GUIUtility.systemCopyBuffer = text;
				Gc.Center(GcLoc.Get("gcm_copied"));
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					header.text = GcLoc.Get("gcm_copied");
				}
			});
			GcUi.CreateButton(window.transform, GcLoc.Get("gcm_close"), new Vector2(0.5f, 0f), new Vector2(130f, 44f), 200f, 44f, delegate
			{
				window.SetActive(false);
				GUIManager.BlockInput(false);
			});
		}
	}
}
namespace GC.Kern.Progression
{
	internal static class BossScaling
	{
		internal static readonly string[] BossKeys = new string[8] { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader", "defeated_frozenking_p3" };

		internal const string EpicLootGuid = "randyknapp.mods.epicloot";

		internal const float EpicLootPercent = 10f;

		internal static ConfigEntry<bool> Automatic = null;

		internal static ConfigEntry<float> PercentPerBoss = null;

		private static int count;

		private static float nextCount;

		private static Player? countedFor;

		private static float spawnedAt;

		private static bool announced;

		internal static int Count => count;

		internal static float Factor
		{
			get
			{
				if (!((Object)(object)Player.m_localPlayer != (Object)null))
				{
					return 1f;
				}
				return 1f + Percent() / 100f * (float)count;
			}
		}

		internal static bool OnGcServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					if (!ZNet.instance.IsServer())
					{
						return GcKern.Server != null;
					}
					return true;
				}
				return false;
			}
		}

		internal static bool Active
		{
			get
			{
				if (count > 0 && (Object)(object)Player.m_localPlayer != (Object)null && OnGcServer)
				{
					return Percent() > 0f;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile config)
		{
			Automatic = Gc.BindSynced(config, "13 - Boss Progression", "Automatic", value: true, "Prozent je besiegtem Hauptboss automatisch: der höchste Ausgleichswert der laufenden GC-Mods (z. B. Tiere 5), mit EpicLoot mindestens 10, ohne erleichternde Mods 0 (wie Valheim). Aus: es gilt PercentPerBoss.");
			PercentPerBoss = Gc.BindSynced(config, "13 - Boss Progression", "PercentPerBoss", 5f, "Gegner und Bosse haben je besiegtem Hauptboss (Eikthyr, Ältester, Bonemass, Moder, Yagluth, Königin, Fader, Kall Mandefimbul) so viel Prozent mehr Leben und machen so viel mehr Schaden, addiert. Gilt nur, wenn Automatic aus ist. Es zählt der eigene Fortschritt jedes Spielers (mit World Advancement Progression seine privaten Schlüssel, mit Guilds_Progress samt Gilden-Fortschritt, ohne diese Mods die Welt).", (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 100f));
		}

		internal static float Percent()
		{
			if (!Automatic.Value)
			{
				return Mathf.Max(0f, PercentPerBoss.Value);
			}
			float num = (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot") ? 10f : 0f);
			foreach (GcModule module in GcKern.Modules)
			{
				if (module.Info.Ausgleich > num && module.On)
				{
					num = module.Info.Ausgleich;
				}
			}
			return num;
		}

		internal static string Source()
		{
			if (!Automatic.Value)
			{
				return "";
			}
			float num = 0f;
			string result = "";
			if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot"))
			{
				num = 10f;
				result = "EpicLoot";
			}
			foreach (GcModule module in GcKern.Modules)
			{
				if (module.Info.Ausgleich > num && module.On)
				{
					num = module.Info.Ausgleich;
					string text = "gck_mod_" + module.Info.Id;
					string text2 = GcLoc.Get(text);
					result = ((text2 == text) ? module.Info.Name : text2);
				}
			}
			return result;
		}

		internal static bool IsFoe(Character? character)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			if ((Object)(object)character == (Object)null || character.IsPlayer() || character.IsTamed())
			{
				return false;
			}
			Faction faction = character.GetFaction();
			if ((int)faction != 0 && (int)faction != 11)
			{
				return (int)faction != 12;
			}
			return false;
		}

		internal static bool Ours(Character? character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			if ((Object)(object)character == (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			ZNetView nview = character.m_nview;
			if (!character.IsPlayer() && character.IsTamed() && (Object)(object)nview != (Object)null && nview.IsValid())
			{
				return nview.IsOwner();
			}
			return false;
		}

		private static int CountBosses()
		{
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			string[] bossKeys = BossKeys;
			foreach (string text in bossKeys)
			{
				if (instance.GetGlobalKey(text))
				{
					num++;
				}
			}
			return num;
		}

		internal static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				countedFor = null;
				count = 0;
				return;
			}
			float time = Time.time;
			if ((Object)(object)localPlayer != (Object)(object)countedFor)
			{
				countedFor = localPlayer;
				spawnedAt = time;
				announced = false;
				count = CountBosses();
				nextCount = time + 2f;
			}
			else
			{
				if (time < nextCount)
				{
					return;
				}
				nextCount = time + 2f;
				int num = CountBosses();
				bool flag = announced || time - spawnedAt > 15f;
				if (num > count && flag && OnGcServer)
				{
					float num2 = Percent();
					if (num2 > 0f)
					{
						string text = Mathf.RoundToInt(num2 * (float)(num - count)).ToString();
						string text2 = Mathf.RoundToInt(num2 * (float)num).ToString();
						MessageHud instance = MessageHud.instance;
						if (instance != null)
						{
							instance.ShowMessage((MessageType)2, GcLoc.Get("gcbp_stronger", text, text2), 0, (Sprite)null, false, true);
						}
					}
				}
				announced = flag;
				count = num;
			}
		}

		internal static string Note()
		{
			string text = Mathf.RoundToInt(Percent()).ToString();
			string text2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? GcLoc.Get("gcsv_bossscale_now", text, count.ToString(), Mathf.RoundToInt(Percent() * (float)count).ToString()) : GcLoc.Get("gcsv_bossscale_rule", text));
			string text3 = Source();
			if (text3.Length <= 0)
			{
				return text2;
			}
			return text2 + " " + GcLoc.Get("gck_bossscale_source", text3);
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class BossScalingDealtPatch
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			if (hit != null && BossScaling.Active && BossScaling.IsFoe(__instance))
			{
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null && (Object)(object)attacker != (Object)(object)__instance && BossScaling.Ours(attacker))
				{
					hit.ApplyModifier(1f / BossScaling.Factor);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class BossScalingTakenPatch
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			if (hit != null && BossScaling.Active && BossScaling.Ours(__instance))
			{
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null && (Object)(object)attacker != (Object)(object)__instance && BossScaling.IsFoe(attacker))
				{
					hit.ApplyModifier(BossScaling.Factor);
				}
			}
		}
	}
}
namespace GC.Shared
{
	public enum GcTaming
	{
		Normal,
		Blocked,
		SimpleAI
	}
	public static class GcHooks
	{
		public static Func<bool>? DungeonMapLargeOpen;

		public static Func<bool>? PortalGuardActive;

		public static Action<TeleportWorld, string>? PortalRename;

		public static Func<int, float>? SpeciesMaxLevel;

		public static Func<float>? SpeciesEffectCap;

		public static Func<Character, Character, bool>? SpeciesEnemyForOrder;

		public static Func<Character, GcTaming>? SpeciesTaming;

		public static Func<bool>? CourierOn;

		public static Func<Player, ItemData, bool>? CourierWhistle;

		public static Func<string>? CourierTooltip;

		public static Func<Procreation, float?>? MateLevel;

		public static int RedCraft;

		public static bool IsDungeonMapLargeOpen()
		{
			try
			{
				return DungeonMapLargeOpen != null && DungeonMapLargeOpen();
			}
			catch
			{
				return false;
			}
		}

		public static bool IsPortalGuardActive()
		{
			try
			{
				return PortalGuardActive != null && PortalGuardActive();
			}
			catch
			{
				return false;
			}
		}

		public static bool IsCourierOn()
		{
			try
			{
				return CourierOn != null && CourierOn();
			}
			catch
			{
				return false;
			}
		}

		public static float? GetMateLevel(Procreation parent)
		{
			try
			{
				return MateLevel?.Invoke(parent);
			}
			catch
			{
				return null;
			}
		}

		public static void Leave(ref int depth)
		{
			depth = Math.Max(0, depth - 1);
		}

		public static int CountUsable(Inventory inventory, string name)
		{
			RedCraft++;
			try
			{
				return inventory.CountItems(name, -1, true);
			}
			finally
			{
				Leave(ref RedCraft);
			}
		}
	}
	public enum GcSeite
	{
		Spieler,
		ServerOptional,
		Alle
	}
	public sealed class GcModInfo
	{
		public string Id = "";

		public string Guid = "";

		public string Name = "";

		public string Version = "";

		public int Stufe = 1;

		public GcSeite Seite;

		public string[] Braucht = Array.Empty<string>();

		public string[] Partner = Array.Empty<string>();

		public string[] Fremd = Array.Empty<string>();

		public string AlteConfig = "";

		public float Ausgleich;
	}
	public sealed class GcServerInfo
	{
		public int Stufe;

		public HashSet<string> Guids = new HashSet<string>(StringComparer.Ordinal);
	}
	public sealed class GcModule
	{
		private readonly HashSet<string> reported = new HashSet<string>();

		public Func<bool>? IsOn;

		public BaseUnityPlugin Plugin { get; }

		public ManualLogSource Log { get; }

		public GcModInfo Info { get; }

		public ConfigFile Config => Plugin.Config;

		public bool FreshConfig { get; }

		public bool Allowed => GcKern.Allowed(Info);

		public bool OnServer => GcKern.ServerHas(Info.Guid);

		public bool On
		{
			get
			{
				try
				{
					return Allowed && (IsOn == null || IsOn());
				}
				catch
				{
					return false;
				}
			}
		}

		internal GcModule(BaseUnityPlugin plugin, ManualLogSource log, GcModInfo info, bool freshConfig)
		{
			Plugin = plugin;
			Log = log;
			Info = info;
			FreshConfig = freshConfig;
		}

		public GcMenuGroup MenuGroup(Func<string, string> text, string? titleKey = null)
		{
			return GcKern.MenuGroup(this, text, titleKey);
		}

		public void TakeOverOldSettings()
		{
			if (!FreshConfig || Info.AlteConfig.Length == 0)
			{
				return;
			}
			string[] array = Info.AlteConfig.Split(new char[2] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				string path = Path.Combine(Paths.ConfigPath, text);
				if (!File.Exists(path))
				{
					continue;
				}
				bool saveOnConfigSet = Config.SaveOnConfigSet;
				try
				{
					Dictionary<string, string> dictionary = GcCfgFile.Read(path);
					int num = 0;
					Config.SaveOnConfigSet = false;
					foreach (ConfigDefinition item in Config.Keys.ToList())
					{
						if (dictionary.TryGetValue(GcCfgFile.Key(item.Section, item.Key), out var value))
						{
							ConfigEntryBase obj = Config[item];
							string serializedValue = obj.GetSerializedValue();
							obj.SetSerializedValue(value);
							if (obj.GetSerializedValue() != serializedValue)
							{
								num++;
							}
						}
					}
					Config.SaveOnConfigSet = saveOnConfigSet;
					Config.Save();
					Log.LogInfo((object)$"Einstellungen aus {text} übernommen: {num} Werte weichen vom Standard ab.");
				}
				catch (Exception ex)
				{
					Config.SaveOnConfigSet = saveOnConfigSet;
					Log.LogWarning((object)("Einstellungen aus " + text + " konnten nicht übernommen werden: " + ex.Message));
				}
			}
		}

		public void Guard(string part, Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				if (reported.Add(part))
				{
					Log.LogWarning((object)$"{part}: {arg}");
				}
			}
		}

		public bool Has(string id)
		{
			return GcKern.ModLoaded(id);
		}
	}
	public static class GcKern
	{
		public const string Guid = "gorduan.gc.kern";

		public const string Name = "GC_Kern";

		public const string Version = "1.1.1";

		public const string GuidPrefix = "gorduan.gc.";

		public static readonly string[] OldPackages = new string[3] { "gorduan.gc_server", "gorduan.gc_client", "gorduan.valheimplusplus" };

		private static readonly List<GcModule> modules = new List<GcModule>();

		private static readonly Dictionary<int, GcMenuSection> sections = new Dictionary<int, GcMenuSection>();

		internal static ConfigEntry<int>? StufeSetting;

		public static IReadOnlyList<GcModule> Modules => modules;

		public static GcServerInfo? Server { get; internal set; }

		public static int HighestLocalStufe
		{
			get
			{
				if (modules.Count != 0)
				{
					return modules.Max((GcModule m) => m.Info.Stufe);
				}
				return 0;
			}
		}

		public static int ServerStufe
		{
			get
			{
				ZNet instance = ZNet.instance;
				if ((Object)(object)instance == (Object)null || instance.IsServer() || Server == null)
				{
					return 6;
				}
				int num = StufeSetting?.Value ?? 0;
				if (num <= 0)
				{
					return Math.Max(1, Server.Stufe);
				}
				return num;
			}
		}

		public static GcModule Register(BaseUnityPlugin plugin, ManualLogSource log, GcModInfo info)
		{
			bool freshConfig = !File.Exists(plugin.Config.ConfigFilePath);
			GcModule gcModule = new GcModule(plugin, log, info, freshConfig);
			modules.Add(gcModule);
			if (((object)plugin).GetType().Assembly != typeof(GcKern).Assembly)
			{
				GcLoc.AddAssembly(((object)plugin).GetType().Assembly, info.Name, log);
			}
			log.LogInfo((object)$"{info.Name} {info.Version} angemeldet: Stufe {info.Stufe}, {SeiteText(info.Seite)}.");
			return gcModule;
		}

		public static bool IsLoaded(string guid)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}

		public static bool ModLoaded(string id)
		{
			return IsLoaded("gorduan.gc." + id);
		}

		internal static bool Allowed(GcModInfo info)
		{
			if (info.Seite == GcSeite.Alle || info.Stufe <= 0)
			{
				return true;
			}
			if (info.Seite == GcSeite.ServerOptional && ServerHas(info.Guid))
			{
				return true;
			}
			return info.Stufe <= ServerStufe;
		}

		internal static bool ServerHas(string guid)
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (instance.IsServer())
			{
				return IsLoaded(guid);
			}
			if (Server != null)
			{
				return Server.Guids.Contains(guid);
			}
			return false;
		}

		public static string StufeName(int stufe)
		{
			return GcLoc.Get("gck_stufe" + stufe);
		}

		public static string SeiteText(GcSeite seite)
		{
			return seite switch
			{
				GcSeite.Spieler => "nur Spieler", 
				GcSeite.ServerOptional => "Spieler, Server optional", 
				_ => "Server und alle Spieler", 
			};
		}

		internal static GcMenuSection Section(int stufe)
		{
			if (!sections.TryGetValue(stufe, out GcMenuSection value))
			{
				string id = ((stufe == 0) ? "gc_kern" : ("gc_stufe" + stufe));
				int order = ((stufe == 0) ? 90 : (stufe * 10));
				value = KernPlugin.Menu.Section(id, order, (string key) => GcLoc.Get((stufe == 0) ? ("gck_kern_" + key) : ("gck_stufe" + stufe + "_" + key)), "");
				sections[stufe] = value;
			}
			return value;
		}

		internal static GcMenuGroup MenuGroup(GcModule module, Func<string, string> text, string? ownTitleKey = null)
		{
			GcModInfo info = module.Info;
			string titleKey = ownTitleKey ?? ("gck_mod_" + info.Id);
			Func<string> title = delegate
			{
				string text2 = GcLoc.Get(titleKey);
				return (!(text2 == titleKey)) ? text2 : info.Name;
			};
			return Section(info.Stufe).Group(titleKey, title, text, info.Guid, () => module.Allowed);
		}
	}
	internal static class GcCfgFile
	{
		public static string Key(string section, string key)
		{
			return section.Trim() + "\u0001" + key.Trim();
		}

		public static Dictionary<string, string> Read(string path)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			string section = "";
			string[] array = File.ReadAllLines(path);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length == 0 || text.StartsWith("#", StringComparison.Ordinal))
				{
					continue;
				}
				if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal))
				{
					section = text.Substring(1, text.Length - 2).Trim();
					continue;
				}
				int num = text.IndexOf('=');
				if (num > 0)
				{
					dictionary[Key(section, text.Substring(0, num))] = text.Substring(num + 1).Trim();
				}
			}
			return dictionary;
		}
	}
	[BepInPlugin("gorduan.gc.kern", "GC_Kern", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("gorduan.gc_server")]
	[BepInIncompatibility("gorduan.gc_client")]
	[BepInIncompatibility("gorduan.valheimplusplus")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class KernPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule Module;

		internal static GcMenu Menu;

		internal static ConfigEntry<KeyboardShortcut>? MenuKey;

		private void Awake()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, new GcModInfo
			{
				Id = "kern",
				Guid = "gorduan.gc.kern",
				Name = "GC_Kern",
				Version = "1.1.1",
				Stufe = 0,
				Seite = GcSeite.Spieler,
				AlteConfig = "gorduan.gc_server.cfg"
			});
			GcLoc.Init("GC_Kern", ((BaseUnityPlugin)this).Logger);
			GcKern.StufeSetting = Gc.BindSynced(((BaseUnityPlugin)this).Config, "1 - Server", "SpielerStufe", 0, "Bis zu welcher Stufe Mods, die nur beim Spieler laufen, auf diesem Server wirken dürfen (1 Sehr Vanilla, 2 Vanilla, 3 Vanilla+, 4 GC leicht, 5 GC). 0 = automatisch: die höchste Stufe der GC-Mods auf dem Server.", (AcceptableValueBase?)(object)new AcceptableValueRange<int>(0, 5));
			Plugin.Init(((BaseUnityPlugin)this).Config);
			BossScaling.Init(((BaseUnityPlugin)this).Config);
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("2 - Menue", "Taste", KeyboardShortcut.Empty, "Taste für das Menü GC Option, im Hauptmenü und im Spiel (nicht im Chat oder in der Konsole). Leer = nur über den Knopf.");
			Module.TakeOverOldSettings();
			new Harmony("gorduan.gc.kern").PatchAll(typeof(KernPlugin).Assembly);
			Menu = new GcMenu(Log, GcMenu.UiText(""));
			Module.MenuGroup(KernText).Main("stufe", (ConfigEntryBase)(object)GcKern.StufeSetting, null, "", StufeNote, 1.0).Main("bossscale", (ConfigEntryBase)(object)BossScaling.Automatic, null, "", BossScaling.Note)
				.Sub("bossscale_percent", (ConfigEntryBase)(object)BossScaling.PercentPerBoss, 1.0, " %")
				.Main("modcheck", (ConfigEntryBase)(object)Plugin.Enabled, () => Plugin.Blocked, "GC_ModCheck")
				.Sub("modcheck_failure", (ConfigEntryBase)(object)Plugin.ShowOnFailure)
				.Sub("modcheck_join", (ConfigEntryBase)(object)Plugin.ShowOnJoinIfMissing)
				.Main("menukey", (ConfigEntryBase)(object)MenuKey);
			Log.LogInfo((object)"GC_Kern 1.1.1 geladen.");
		}

		private static string KernText(string key)
		{
			string text = GcLoc.Get("gck_" + key);
			if (!(text != "gck_" + key))
			{
				return GcLoc.Get("gcsv_" + key);
			}
			return text;
		}

		private static string StufeNote()
		{
			ZNet instance = ZNet.instance;
			int num;
			if ((Object)(object)instance != (Object)null && !instance.IsServer())
			{
				num = GcKern.ServerStufe;
			}
			else
			{
				int num2 = GcKern.StufeSetting?.Value ?? 0;
				num = ((num2 > 0) ? num2 : Math.Max(1, GcKern.HighestLocalStufe));
			}
			if (num < 6)
			{
				return GcLoc.Get("gck_stufe_now", num, GcKern.StufeName(num));
			}
			return GcLoc.Get("gck_stufe_now_free");
		}

		private void Start()
		{
			Menu.LogBlocked();
			if (!Gc.IsHeadless)
			{
				Module.Guard("ValheimPlus im Menü", delegate
				{
					VPlusOptions.Register(Menu);
				});
			}
			foreach (GcModule module in GcKern.Modules)
			{
				string[] partner = module.Info.Partner;
				foreach (string text in partner)
				{
					if (!GcKern.ModLoaded(text))
					{
						Log.LogInfo((object)(module.Info.Name + ": Partner gorduan.gc." + text + " fehlt, die Mod läuft ohne dessen Teil."));
					}
				}
			}
		}

		private void Update()
		{
			if (!Gc.IsHeadless)
			{
				Module.Guard("Menü-Taste", delegate
				{
					Menu.CheckHotkey();
				});
				Module.Guard("Menü", delegate
				{
					Menu.Update();
				});
				Module.Guard("Boss-Fortschritt", BossScaling.Tick);
			}
		}
	}
	public sealed class GcMenuSection
	{
		private readonly List<object> groups;

		private readonly Func<string, string> text;

		internal GcMenuSection(Dictionary<string, object> data, Func<string, string> text)
		{
			groups = (List<object>)data["groups"];
			this.text = text;
		}

		public GcMenuGroup Group(string id)
		{
			List<object> list = new List<object>();
			Func<string, string> t = text;
			groups.Add(new Dictionary<string, object>
			{
				["id"] = id,
				["title"] = (Func<string>)(() => t("group_" + id)),
				["items"] = list
			});
			return new GcMenuGroup(list, text);
		}

		public GcMenuGroup Group(string id, Func<string> title, Func<string, string> groupText, string guid, Func<bool>? allowed = null)
		{
			List<object> list = new List<object>();
			Dictionary<string, object> dictionary = new Dictionary<string, object>
			{
				["id"] = id,
				["title"] = title,
				["items"] = list,
				["guid"] = guid
			};
			if (allowed != null)
			{
				dictionary["allowed"] = allowed;
			}
			groups.Add(dictionary);
			return new GcMenuGroup(list, groupText);
		}
	}
	public sealed class GcMenuGroup
	{
		private readonly List<object> items;

		private readonly Func<string, string> text;

		internal GcMenuGroup(List<object> items, Func<string, string> text)
		{
			this.items = items;
			this.text = text;
		}

		public GcMenuGroup Main(string key, ConfigEntryBase entry, Func<bool>? blocked = null, string oldMod = "", Func<string>? note = null, double step = 0.0, string unit = "", Func<bool>? requires = null, Func<bool>? locked = null)
		{
			return Add(key, entry, 0, blocked, oldMod, note, step, unit, requires, locked);
		}

		public GcMenuGroup Sub(string key, ConfigEntryBase entry, double step = 0.0, string unit = "", Func<bool>? blocked = null, string oldMod = "", Func<bool>? requires = null, Func<bool>? locked = null)
		{
			return Add(key, entry, 1, blocked, oldMod, null, step, unit, requires, locked);
		}

		private GcMenuGroup Add(string key, ConfigEntryBase entry, int level, Func<bool>? blocked, string oldMod, Func<string>? note, double step, string unit, Func<bool>? requires, Func<bool>? locked)
		{
			Func<string, string> t = text;
			Dictionary<string, object> dictionary = new Dictionary<string, object>
			{
				["key"] = key,
				["entry"] = entry,
				["name"] = (Func<string>)(() => t("t_" + key + "_name")),
				["desc"] = (Func<string>)(() => t("t_" + key + "_desc")),
				["enumText"] = (Func<string, string>)((string value) => t("enum_" + value)),
				["level"] = level,
				["step"] = step,
				["unit"] = unit,
				["oldMod"] = oldMod
			};
			if (blocked != null)
			{
				dictionary["blocked"] = blocked;
			}
			if (note != null)
			{
				dictionary["note"] = note;
			}
			if (requires != null)
			{
				dictionary["requires"] = requires;
			}
			if (locked != null)
			{
				dictionary["locked"] = locked;
			}
			items.Add(dictionary);
			return this;
		}
	}
	public sealed class GcMenu
	{
		private sealed class Row
		{
			public Dictionary<string, object> Item;

			public ConfigEntryBase Entry;

			public string Guid = "";

			public Func<bool>? Allowed;

			public int Level;

			public bool Server;

			public GameObject Root;

			public Row? Parent;

			public readonly List<Row> Subs = new List<Row>();

			public Text Name;

			public Text Description;

			public Text Scope;

			public string BaseDescription = "";

			public EditorKind Kind;

			public Button? Main;

			public Text? MainLabel;

			public Button? Minus;

			public Button? Plus;

			public InputField? Input;

			public bool InputError;

			public object[]? Choices;

			public bool Foreign;

			public ForeignMod? Mod;

			public SyncKind Sync;

			public bool ReadOnly;

			public Func<bool>? ReadOnlyCheck;

			public object? SyncTag;

			public string Search = "";

			public Button? Reset;

			public bool HideDefault;

			public bool Editable;

			public bool Visible;
		}

		private sealed class Block
		{
			public GameObject Header;

			public readonly List<Row> Rows = new List<Row>();

			public readonly List<Block> Children = new List<Block>();
		}

		private enum SyncKind
		{
			Local,
			Jotunn,
			ServerSync
		}

		private sealed class ForeignEntry
		{
			public ConfigEntryBase Entry;

			public string Name = "";

			public string Section = "";

			public string Description = "";

			public SyncKind Sync;

			public Func<bool>? ReadOnlyCheck;

			public bool HideDefault;

			public bool Advanced;

			public int Order;

			public int Index;

			public string Search = "";
		}

		private sealed class ForeignGroup
		{
			public GameObject Header;

			public readonly List<Row> Rows = new List<Row>();
		}

		private sealed class ForeignMod
		{
			public string Guid = "";

			public string Name = "";

			public string Version = "";

			public bool HasSync;

			public readonly List<ForeignEntry> Entries = new List<ForeignEntry>();

			public string Search = "";

			public GameObject Header;

			public Text HeaderLabel;

			public GameObject Body;

			public bool Built;

			public readonly List<Row> Rows = new List<Row>();

			public GameObject? ClientHeader;

			public GameObject? ServerHeader;

			public readonly List<ForeignGroup> ClientGroups = new List<ForeignGroup>();

			public readonly List<ForeignGroup> ServerGroups = new List<ForeignGroup>();
		}

		private enum View
		{
			Settings,
			Mods,
			Profiles
		}

		private sealed class ModRow
		{
			public ModSwitch.Mod Mod;

			public GameObject Root;

			public Toggle Toggle;

			public Text Title;

			public Text Sub;

			public Text Status;
		}

		private sealed class ProfileRow
		{
			public ModSwitch.Profile Profile;

			public GameObject Root;

			public Text Info;

			public Button Load;

			public Button Overwrite;

			public Button Delete;

			public string Pending = "";

			public float PendingUntil;
		}

		private enum EditorKind
		{
			Toggle,
			Cycle,
			Key,
			Number,
			Text,
			ReadOnly
		}

		public const string SharedSlot = "GC.Options.Registry.v2";

		public const string ButtonName = "GC_OptionButton_v2";

		private static readonly Color OnColor = new Color(0.45f, 0.95f, 0.45f);

		private static readonly Color OffColor = new Color(1f, 0.45f, 0.4f);

		private static readonly Color MutedColor = new Color(0.78f, 0.72f, 0.62f);

		private static readonly Color ValueColor = new Color(1f, 0.85f, 0.55f);

		private static readonly Color LockedColor = new Color(0.6f, 0.58f, 0.55f);

		private static readonly KeyCode[] Modifiers;

		private static KeyCode[]? allKeys;

		private static MethodInfo? syncMethod;

		private readonly ManualLogSource log;

		private readonly Func<string, string> ui;

		private readonly bool canHost;

		private readonly List<object> registry;

		private readonly List<Dictionary<string, object>> ownSections = new List<Dictionary<string, object>>();

		private readonly List<Row> rows = new List<Row>();

		private readonly List<Block> sections = new List<Block>();

		private GameObject? window;

		private RectTransform? content;

		private Toggle? showServer;

		private static bool serverRulesShown;

		private InputField? searchField;

		private string query = "";

		private string pendingQuery = "";

		private float queryAt = -1f;

		private bool focusSearch;

		private InputField? typingField;

		private int typingFrame = -10;

		private Vector2 builtSize;

		private int builtForeign;

		private bool wide;

		private int closedFrame = -10;

		private int pendingUnblocks;

		private GameObject? emptyHint;

		private Text? emptyLabel;

		private Text? hintLabel;

		private Button? menuButton;

		private int builtShape = -1;

		private float nextRefresh;

		private Row? capturing;

		private KeyCode capturedModifier;

		private bool openedFromPause;

		private int captureFrame = -1;

		private string lastError = "";

		private const float WindowMargin = 40f;

		private const float MaxWindowWidth = 1800f;

		private const float WideWidth = 1400f;

		private const float TopBarHeight = 92f;

		private const float SearchWidth = 420f;

		private const float NameWidth = 340f;

		private static readonly Color ErrorColor;

		private Button? mainMenuButton;

		private static readonly Vector3[] MenuCorners;

		private static readonly Color SubHeaderColor;

		private static readonly Color SectionColor;

		private readonly List<ForeignMod> foreignMods = new List<ForeignMod>();

		private GameObject? foreignHeader;

		private static readonly HashSet<string> ExpandedMods;

		private const string VPlusGuid = "org.bepinex.plugins.valheim_plus";

		private static readonly Dictionary<Type, FieldInfo?> LocalBaseFields;

		private readonly HashSet<string> searchClosed = new HashSet<string>(StringComparer.Ordinal);

		private const int AutoOpenLimit = 6;

		private const int DeepSearchLength = 3;

		private const float TabWidth = 190f;

		private static readonly Color GoodColor;

		private static readonly Color WarnColor;

		private static View lastView;

		private View view;

		private RectTransform? innerRect;

		private readonly List<(View View, Text? Label)> tabs = new List<(View, Text)>();

		private GameObject? settingsArea;

		private GameObject? settingsTools;

		private GameObject? modsArea;

		private GameObject? modsTools;

		private RectTransform? modsContent;

		private GameObject? modsNoPatcher;

		private InputField? modsSearch;

		private string modsQuery = "";

		private Text? modsStatus;

		private string modsMessage = "";

		private readonly List<ModRow> modRows = new List<ModRow>();

		private GameObject? profilesArea;

		private GameObject? profilesTools;

		private RectTransform? profilesContent;

		private GameObject? profilesEmpty;

		private InputField? profileName;

		private Text? profilesStatus;

		private Text? profileSaveLabel;

		private string profilesMessage = "";

		private string savePending = "";

		private float savePendingUntil;

		private readonly List<ProfileRow> profileRows = new List<ProfileRow>();

		private bool pausedByKey;

		private static readonly Dictionary<ConfigEntryBase, (bool Has, double Min, double Max)> Ranges;

		public static bool HoldsInput
		{
			get
			{
				if (KernPlugin.Menu != null)
				{
					if (!KernPlugin.Menu.IsOpen)
					{
						return Time.frameCount <= KernPlugin.Menu.closedFrame + 1;
					}
					return true;
				}
				return false;
			}
		}

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)window != (Object)null)
				{
					return window.activeSelf;
				}
				return false;
			}
		}

		public static bool CanChangeServer
		{
			get
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return false;
				}
				if (ZNet.instance.IsServer())
				{
					return true;
				}
				if (SynchronizationManager.Instance != null)
				{
					return SynchronizationManager.Instance.PlayerIsAdmin;
				}
				return false;
			}
		}

		public event Action? Closed;

		public GcMenu(ManualLogSource log, Func<string, string> ui, bool canHost = true)
		{
			this.log = log;
			this.ui = ui;
			this.canHost = canHost;
			registry = SharedRegistry();
		}

		public static Func<string, string> UiText(string ownPrefix)
		{
			return delegate(string name)
			{
				if (ownPrefix.Length > 0)
				{
					string text = GcLoc.Get(ownPrefix + name);
					if (text != ownPrefix + name)
					{
						return text;
					}
				}
				return GcLoc.Get("gco_" + name);
			};
		}

		public static bool CanChangeServerSetting(string guid)
		{
			if (CanChangeServer)
			{
				return ModOnServer(guid);
			}
			return false;
		}

		private static bool ModOnServer(string guid)
		{
			try
			{
				return guid.Length == 0 || ModCompatibility.IsModuleOnServer(guid);
			}
			catch
			{
				return false;
			}
		}

		private static List<object> SharedRegistry()
		{
			AppDomain currentDomain = AppDomain.CurrentDomain;
			lock (typeof(object))
			{
				List<object> list = currentDomain.GetData("GC.Options.Registry.v2") as List<object>;
				if (list == null)
				{
					list = new List<object>();
					currentDomain.SetData("GC.Options.Registry.v2", list);
				}
				return list;
			}
		}

		public GcMenuSection Section(string id, int order, Func<string, string> text, string guid)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>
			{
				["id"] = id,
				["order"] = order,
				["guid"] = guid,
				["title"] = (Func<string>)(() => text("title")),
				["groups"] = new List<object>()
			};
			lock (registry)
			{
				registry.RemoveAll((object o) => o is Dictionary<string, object> dictionary2 && dictionary2.TryGetValue("id", out var value) && value is string text2 && text2 == id);
				registry.Add(dictionary);
			}
			ownSections.Add(dictionary);
			return new GcMenuSection(dictionary, text);
		}

		public void LogBlocked()
		{
			foreach (Dictionary<string, object> ownSection in ownSections)
			{
				foreach (Dictionary<string, object> item in Children(ownSection, "groups"))
				{
					foreach (Dictionary<string, object> item2 in Children(item, "items"))
					{
						if (item2.TryGetValue("blocked", out var value) && value is Func<bool> f && Call(f))
						{
							log.LogWarning((object)("Alte Einzelmod " + Str(item2, "oldMod") + " ist noch installiert. Die Funktion '" + Str(item2, "key") + "' bleibt aus, bis die alte Mod entfernt ist."));
						}
					}
				}
			}
		}

		private static List<Dictionary<string, object>> Children(Dictionary<string, object> data, string key)
		{
			if (data.TryGetValue(key, out object value) && value is List<object> list)
			{
				lock (list)
				{
					return list.OfType<Dictionary<string, object>>().ToList();
				}
			}
			return new List<Dictionary<string, object>>();
		}

		private static string Str(Dictionary<string, object> data, string key)
		{
			if (!data.TryGetValue(key, out object value) || !(value is string result))
			{
				return "";
			}
			return result;
		}

		private static int Int(Dictionary<string, object> data, string key, int fallback)
		{
			if (data.TryGetValue(key, out object value) && value is int)
			{
				return (int)value;
			}
			return fallback;
		}

		private static string TextOf(Dictionary<string, object> data, string key)
		{
			try
			{
				object value;
				return (data.TryGetValue(key, out value) && value is Func<string> func) ? (func() ?? "") : "";
			}
			catch
			{
				return "";
			}
		}

		private static bool Call(Func<bool> f)
		{
			try
			{
				return f();
			}
			catch
			{
				return false;
			}
		}

		private List<Dictionary<string, object>> Sections()
		{
			lock (registry)
			{
				return (from s in registry.OfType<Dictionary<string, object>>()
					orderby Int(s, "order", 100)
					select s).ToList();
			}
		}

		private void LogError(string where, Exception e)
		{
			string text = where + ": " + e.Message;
			if (text != lastError)
			{
				lastError = text;
				log.LogError((object)$"Menü GC Option, {text}\n{e}");
			}
		}

		public void Update()
		{
			if (Gc.IsHeadless || !canHost)
			{
				return;
			}
			while (pendingUnblocks > 0 && Time.frameCount > closedFrame)
			{
				pendingUnblocks--;
				GUIManager.BlockInput(false);
			}
			try
			{
				EnsurePauseButton();
				EnsureMainMenuButton();
				FitMainMenu();
				if (!IsOpen)
				{
					return;
				}
				if (capturing != null)
				{
					Capture();
					return;
				}
				if (focusSearch && (Object)(object)searchField != (Object)null)
				{
					focusSearch = false;
					((Selectable)searchField).Select();
					searchField.ActivateInputField();
				}
				InputField val = Typing();
				if ((Object)(object)val != (Object)null)
				{
					typingField = val;
					typingFrame = Time.frameCount;
				}
				if (Input.GetKeyDown((KeyCode)27) && (Time.frameCount - typingFrame > 1 || !((Object)(object)typingField != (Object)null) || !((Object)(object)typingField != (Object)(object)searchField) || !((Object)(object)typingField != (Object)(object)modsSearch)))
				{
					Hide();
					return;
				}
				if (queryAt >= 0f && Time.unscaledTime >= queryAt)
				{
					queryAt = -1f;
					if (pendingQuery != query)
					{
						query = pendingQuery;
						searchClosed.Clear();
						Refresh();
					}
				}
				if (Time.unscaledTime >= nextRefresh)
				{
					nextRefresh = Time.unscaledTime + 0.5f;
					if (Shape() != builtShape)
					{
						RebuildOpen();
					}
					else
					{
						Refresh();
					}
				}
			}
			catch (Exception e)
			{
				LogError("Update", e);
			}
		}

		public bool Show()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (IsOpen)
			{
				return true;
			}
			if (Gc.IsHeadless || GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				return false;
			}
			capturing = null;
			capturedModifier = (KeyCode)0;
			try
			{
				if ((Object)(object)window != (Object)null && (WindowSize() != builtSize || ForeignCount() != builtForeign))
				{
					Object.Destroy((Object)(object)window);
					window = null;
					builtShape = -1;
				}
				Build();
				ClearSearch();
				SwitchView(lastView);
				focusSearch = view == View.Settings;
			}
			catch (Exception e)
			{
				LogError("Aufbau", e);
				if ((Object)(object)window != (Object)null)
				{
					Object.Destroy((Object)(object)window);
				}
				window = null;
				builtShape = -1;
				return false;
			}
			window.SetActive(true);
			window.transform.SetAsLastSibling();
			GUIManager.BlockInput(true);
			return true;
		}

		public void Hide()
		{
			capturing = null;
			if (IsOpen)
			{
				window.SetActive(false);
				closedFrame = Time.frameCount;
				pendingUnblocks++;
				try
				{
					this.Closed?.Invoke();
				}
				catch (Exception e)
				{
					LogError("Schließen", e);
				}
				if (openedFromPause)
				{
					if ((Object)(object)Menu.instance != (Object)null)
					{
						Menu.instance.Show();
					}
					else
					{
						Game.Unpause();
					}
				}
				else if (pausedByKey)
				{
					Game.Unpause();
				}
			}
			openedFromPause = false;
			pausedByKey = false;
		}

		private int Shape()
		{
			return Sections().Sum((Dictionary<string, object> s) => 1000 + Children(s, "groups").Sum((Dictionary<string, object> g) => 1 + Children(g, "items").Count));
		}

		private void Build()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_054e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			int num = Shape();
			if ((Object)(object)window != (Object)null && num == builtShape)
			{
				return;
			}
			if ((Object)(object)window != (Object)null)
			{
				Object.Destroy((Object)(object)window);
				window = null;
			}
			builtShape = -1;
			rows.Clear();
			sections.Clear();
			foreignMods.Clear();
			foreignHeader = null;
			Vector2 val = (builtSize = WindowSize());
			builtForeign = ForeignCount();
			wide = val.x >= 1400f;
			window = GcUi.CreateWindow("GC_Option_Window", val.x, val.y, out Text header, out RectTransform inner);
			header.text = ui("title");
			innerRect = inner;
			modsArea = (modsTools = (profilesArea = (profilesTools = null)));
			modsContent = (profilesContent = null);
			modRows.Clear();
			profileRows.Clear();
			BuildTopBar(inner);
			BuildModsTools(inner);
			BuildProfilesTools(inner);
			GameObject val2 = new GameObject("ScrollArea", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent((Transform)(object)inner, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val3.offsetMin = Vector2.zero;
			val3.offsetMax = new Vector2(0f, -92f);
			settingsArea = val2;
			content = GcUi.CreateScroll((Transform)(object)val3, val.x - 88f, val.y - 172f - 92f);
			emptyHint = HintRow((Transform)(object)content, ui("nothing"), out Text label);
			emptyLabel = label;
			HashSet<ConfigEntryBase> hashSet = new HashSet<ConfigEntryBase>();
			foreach (Dictionary<string, object> item in Sections())
			{
				string text = Str(item, "guid");
				string text2 = TextOf(item, "title");
				Block block = new Block
				{
					Header = Header((Transform)(object)content, text2, 28, GUIManager.Instance.ValheimOrange, norse: true, 46f)
				};
				sections.Add(block);
				foreach (Dictionary<string, object> item2 in Children(item, "groups"))
				{
					List<Dictionary<string, object>> list = Children(item2, "items");
					if (list.Count == 0)
					{
						continue;
					}
					string text3 = TextOf(item2, "title");
					Block block2 = new Block
					{
						Header = Header((Transform)(object)content, text3, 22, new Color(1f, 0.75f, 0.4f), norse: false, 34f)
					};
					block.Children.Add(block2);
					string text4 = Str(item2, "guid");
					object value;
					Func<bool> allowed = (item2.TryGetValue("allowed", out value) ? (value as Func<bool>) : null);
					Row row = null;
					foreach (Dictionary<string, object> item3 in list)
					{
						Row row2 = CreateRow(item3, (text4.Length > 0) ? text4 : text, (Transform)(object)content);
						if (row2 != null)
						{
							hashSet.Add(row2.Entry);
							row2.Allowed = allowed;
							row2.Search = SearchText(TextOf(item3, "name"), TextOf(item3, "desc"), text3, text2, row2.Entry.Definition.Key, row2.Guid, ModuleName(row2.Guid));
							if (row2.Level == 0)
							{
								row = row2;
							}
							else if (row != null)
							{
								row2.Parent = row;
								row.Subs.Add(row2);
							}
							rows.Add(row2);
							block2.Rows.Add(row2);
						}
					}
				}
			}
			BuildForeign(hashSet);
			hintLabel = GcUi.CreateLabel(window.transform, ui("hint_config"), new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(44f, 64f), new Vector2(-44f, 86f), 15, (TextAnchor)4, MutedColor);
			((Graphic)hintLabel).raycastTarget = false;
			GcUi.CreateButton(window.transform, ui("close"), new Vector2(0.5f, 0f), new Vector2(0f, 38f), 200f, 42f, Hide);
			builtShape = num;
		}

		private static string ModuleName(string guid)
		{
			return GcKern.Modules.FirstOrDefault((GcModule m) => m.Info.Guid == guid)?.Info.Name ?? "";
		}

		private static Vector2 WindowSize()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			? val2;
			if ((Object)(object)GUIManager.CustomGUIFront != (Object)null)
			{
				Transform transform = GUIManager.CustomGUIFront.transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val != null)
				{
					Rect rect = val.rect;
					if (((Rect)(ref rect)).width > 0f)
					{
						rect = val.rect;
						val2 = ((Rect)(ref rect)).size;
						goto IL_0054;
					}
				}
			}
			val2 = new Vector2(1920f, 1080f);
			goto IL_0054;
			IL_0054:
			Vector2 val3 = (Vector2)val2;
			float num = Mathf.Clamp(val3.x - 80f, Mathf.Min(900f, val3.x), 1800f);
			float num2 = Mathf.Max(val3.y - 80f, Mathf.Min(640f, val3.y));
			return new Vector2(Mathf.Round(num), Mathf.Round(num2));
		}

		private void BuildTopBar(RectTransform inner)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			BuildTabs(inner);
			settingsTools = ToolRow(inner, "SettingsTools");
			RectTransform val = (RectTransform)settingsTools.transform;
			GameObject val2 = GUIManager.Instance.CreateInputField((Transform)(object)val, new Vector2(0f, 1f), new Vector2(0f, 1f), Vector2.zero, (ContentType)0, ui("search"), 18, 420f, 34f);
			((Object)val2).name = "Search";
			RectTransform val3 = (RectTransform)val2.transform;
			val3.pivot = new Vector2(0f, 1f);
			val3.anchoredPosition = new Vector2(16f, 0f);
			searchField = val2.GetComponent<InputField>();
			searchField.lineType = (LineType)0;
			((UnityEvent<string>)(object)searchField.onValueChanged).AddListener((UnityAction<string>)delegate(string text)
			{
				pendingQuery = NormalizeSearch(text);
				queryAt = Time.unscaledTime + 0.2f;
			});
			GameObject val4 = GUIManager.Instance.CreateToggle((Transform)(object)val, 28f, 28f);
			((Object)val4).name = "ShowServer";
			RectTransform val5 = (RectTransform)val4.transform;
			((Transform)val5).SetParent((Transform)(object)val, false);
			((Transform)val5).localScale = Vector3.one;
			Vector2 val6 = default(Vector2);
			((Vector2)(ref val6))..ctor(0f, 1f);
			val5.anchorMax = val6;
			val5.anchorMin = val6;
			val5.pivot = new Vector2(0f, 1f);
			val5.anchoredPosition = new Vector2(468f, -3f);
			Transform obj = val4.transform.Find("Background");
			RectTransform val7 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (val7 != null)
			{
				Vector2 val8 = default(Vector2);
				((Vector2)(ref val8))..ctor(0.5f, 0.5f);
				val7.pivot = val8;
				val6 = (val7.anchorMin = (val7.anchorMax = val8));
				val7.anchoredPosition = Vector2.zero;
			}
			Transform obj2 = val4.transform.Find("Label");
			Text val11 = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null);
			if ((Object)(object)val11 != (Object)null)
			{
				val11.text = ui("show_server");
				val11.font = GUIManager.Instance.AveriaSerifBold;
				val11.fontSize = 18;
				((Graphic)val11).color = MutedColor;
				val11.alignment = (TextAnchor)3;
				val11.horizontalOverflow = (HorizontalWrapMode)1;
				RectTransform rectTransform = ((Graphic)val11).rectTransform;
				rectTransform.anchorMin = new Vector2(1f, 0f);
				rectTransform.anchorMax = new Vector2(1f, 1f);
				rectTransform.pivot = new Vector2(0f, 0.5f);
				rectTransform.offsetMin = new Vector2(12f, 0f);
				rectTransform.offsetMax = new Vector2(612f, 0f);
				((Shadow)((Component)val11).gameObject.AddComponent<Outline>()).effectColor = Color.black;
			}
			showServer = val4.GetComponent<Toggle>();
			showServer.isOn = serverRulesShown;
			((UnityEvent<bool>)(object)showServer.onValueChanged).AddListener((UnityAction<bool>)delegate(bool on)
			{
				serverRulesShown = on;
				Refresh();
			});
		}

		private void ClearSearch()
		{
			query = (pendingQuery = "");
			queryAt = -1f;
			searchClosed.Clear();
			if ((Object)(object)searchField != (Object)null && searchField.text.Length > 0)
			{
				searchField.text = "";
			}
			queryAt = -1f;
		}

		private static string NormalizeSearch(string text)
		{
			return text.Trim().ToLowerInvariant();
		}

		private static string SearchText(params string[] parts)
		{
			return string.Join(" ", parts).ToLowerInvariant();
		}

		private static InputField? Typing()
		{
			GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null);
			InputField val2 = default(InputField);
			if (!((Object)(object)val != (Object)null) || !val.TryGetComponent<InputField>(ref val2) || !val2.isFocused)
			{
				return null;
			}
			return val2;
		}

		private GameObject Header(Transform parent, string text, int size, Color color, bool norse, float height)
		{
			//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_0037: 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_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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			GameObject val = new GameObject("Header", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			val.transform.SetParent(parent, false);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.minHeight = height;
			component.preferredHeight = height;
			((Graphic)GcUi.CreateLabel(val.transform, text, Vector2.zero, Vector2.one, new Vector2(4f, 0f), Vector2.zero, size, (TextAnchor)6, color, norse)).raycastTarget = false;
			return val;
		}

		private GameObject HintRow(Transform parent, string text, out Text label)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Hint", new Type[2]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup)
			});
			val.transform.SetParent(parent, false);
			VerticalLayoutGroup component = val.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			((LayoutGroup)component).padding = new RectOffset(8, 8, 16, 16);
			label = FlowText(val.transform, text, 18, MutedColor);
			return val;
		}

		private static Text FlowText(Transform parent, string text, int size, Color color)
		{
			//IL_0013: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.Instance;
			Text component = instance.CreateText(text, parent, new Vector2(0f, 1f), new Vector2(1f, 1f), Vector2.zero, instance.AveriaSerifBold, size, color, true, Color.black, 100f, 20f, false).GetComponent<Text>();
			component.alignment = (TextAnchor)0;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)1;
			component.supportRichText = true;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private Row? CreateRow(Dictionary<string, object> item, string guid, Transform parent, ForeignEntry? foreign = null)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Expected O, but got Unknown
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Expected O, but got Unknown
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0530: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_0672: Unknown result type (might be due to invalid IL or missing references)
			if (item.TryGetValue("entry", out object value))
			{
				ConfigEntryBase val = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
				if (val != null)
				{
					object[] choices = Choices(val);
					EditorKind editorKind = KindOf(val.SettingType, choices);
					int num = ((Int(item, "level", 0) > 0) ? 1 : 0);
					GameObject val2 = new GameObject("Row", new Type[3]
					{
						typeof(RectTransform),
						typeof(HorizontalLayoutGroup),
						typeof(LayoutElement)
					});
					val2.transform.SetParent(parent, false);
					HorizontalLayoutGroup component = val2.GetComponent<HorizontalLayoutGroup>();
					((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
					((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
					((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
					((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
					((LayoutGroup)component).childAlignment = (TextAnchor)3;
					((HorizontalOrVerticalLayoutGroup)component).spacing = 12f;
					((LayoutGroup)component).padding = new RectOffset(10 + num * 36, 4, (num == 0) ? 8 : 4, (num == 0) ? 8 : 4);
					val2.GetComponent<LayoutElement>().minHeight = ((num == 0) ? 54f : 44f);
					string text = TextOf(item, "desc");
					Text name;
					Text description;
					if (wide)
					{
						name = FlowText(Cell(val2.transform, 340f - (float)num * 36f, 0f).transform, TextOf(item, "name"), (num == 0) ? 20 : 17, Color.white);
						description = FlowText(Cell(val2.transform, 220f, 1f).transform, text, 15, MutedColor);
					}
					else
					{
						GameObject obj = Cell(val2.transform, 220f, 1f);
						((HorizontalOrVerticalLayoutGroup)obj.GetComponent<VerticalLayoutGroup>()).spacing = 2f;
						name = FlowText(obj.transform, TextOf(item, "name"), (num == 0) ? 20 : 17, Color.white);
						description = FlowText(obj.transform, text, 15, MutedColor);
					}
					GameObject val3 = new GameObject("Scope", new Type[2]
					{
						typeof(RectTransform),
						typeof(LayoutElement)
					});
					val3.transform.SetParent(val2.transform, false);
					LayoutElement component2 = val3.GetComponent<LayoutElement>();
					float minWidth = (component2.preferredWidth = (wide ? 180f : 160f));
					component2.minWidth = minWidth;
					minWidth = (component2.preferredHeight = 40f);
					component2.minHeight = minWidth;
					Text val4 = GcUi.CreateLabel(val3.transform, "", Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero, 14, (TextAnchor)5, MutedColor);
					((Graphic)val4).raycastTarget = false;
					float num4 = (wide ? 260f : 200f);
					GameObject val5 = new GameObject("Control", new Type[2]
					{
						typeof(RectTransform),
						typeof(LayoutElement)
					});
					val5.transform.SetParent(val2.transform, false);
					LayoutElement component3 = val5.GetComponent<LayoutElement>();
					minWidth = (component3.preferredWidth = num4);
					component3.minWidth = minWidth;
					minWidth = (component3.preferredHeight = 40f);
					component3.minHeight = minWidth;
			

GC_Leiter.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Ladder;
using GC.Shared;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Leiter")]
[assembly: AssemblyTitle("GC_Leiter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModLeiter
{
	[BepInPlugin("gorduan.gc.leiter", "GC_Leiter", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.leiter");
			GC.Server.Ladder.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			Module.TakeOverOldSettings();
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("ladder", (ConfigEntryBase)(object)GC.Server.Ladder.Plugin.Enabled, (Func<bool>)(() => GC.Server.Ladder.Plugin.Blocked), "GC_Ladder", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("ladder_cost", (ConfigEntryBase)(object)GC.Server.Ladder.Plugin.WoodCost, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("ladder_exit", (ConfigEntryBase)(object)GC.Server.Ladder.Plugin.ExitDistance, 0.1, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}
	}
	internal static class GcMod
	{
		public const string Id = "leiter";

		public const string Guid = "gorduan.gc.leiter";

		public const string Name = "GC_Leiter";

		public const string Version = "1.8.1";

		public const int Stufe = 4;

		public static GcModInfo Info => new GcModInfo
		{
			Id = "leiter",
			Guid = "gorduan.gc.leiter",
			Name = "GC_Leiter",
			Version = "1.8.1",
			Stufe = 4,
			Seite = (GcSeite)2,
			Braucht = Array.Empty<string>(),
			Partner = Array.Empty<string>(),
			Fremd = Array.Empty<string>(),
			AlteConfig = "gorduan.gc_server.cfg",
			Ausgleich = 0f
		};
	}
}
namespace GC.Server.Ladder
{
	internal static class Plugin
	{
		public const string Guid = "gorduan.gc_ladder";

		public const string ModName = "GC_Ladder";

		public const string Version = "1.0.0";

		internal const string PrefabName = "GC_Ladder";

		internal const string ShortPrefabName = "GC_Ladder_1m";

		private const float HalfWidth = 0.3f;

		private const float RailThickness = 0.09f;

		private const float RungThickness = 0.05f;

		private const float RungSpacing = 0.33f;

		internal static Piece? OldLadderPiece;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static Piece? LadderPiece;

		internal static ConfigEntry<int> WoodCost;

		internal static ConfigEntry<float> ExitDistance;

		internal static bool Blocked => Chainloader.PluginInfos.ContainsKey("gorduan.gc_ladder");

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return !Blocked;
				}
				return false;
			}
		}

		internal static int PieceCost => Mathf.Max(1, Mathf.CeilToInt((float)WoodCost.Value / 2f));

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "1 - Ladder", "Enabled", true, "Leiter baubar und benutzbar (wird vom Server vorgegeben, auch im Menü GC Option).", (AcceptableValueBase)null);
			Enabled.SettingChanged += delegate
			{
				ApplyEnabled();
			};
			WoodCost = Gc.BindSynced<int>(Config, "1 - Ladder", "WoodCost", 4, "Holzkosten pro 2 m Leiter. Ein Leiterstück ist 1 m hoch und kostet die Hälfte (aufgerundet).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50));
			WoodCost.SettingChanged += delegate
			{
				ApplyCost();
			};
			ExitDistance = Gc.Bind<float>(Config, "1 - Ladder", "ExitDistance", 0.8f, "Abstand von der Leiter beim Absteigen in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 2f));
			PrefabManager.OnVanillaPrefabsAvailable += CreateLadder;
		}

		private static void CreateLadder()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_01b6: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreateLadder;
			if (Blocked)
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("wood_pole");
			GameObject val = (((Object)(object)prefab != (Object)null) ? Build("GC_Ladder_1m", "wood_pole", prefab, 1f) : null);
			if ((Object)(object)val == (Object)null || (Object)(object)prefab == (Object)null)
			{
				Log.LogError((object)"wood_pole nicht gefunden, Leiter wird nicht erstellt.");
				return;
			}
			Sprite icon = LadderIcon();
			Piece val2 = (LadderPiece = val.GetComponent<Piece>());
			val2.m_enabled = On;
			val2.m_name = GcLoc.Get("gcld_name", Array.Empty<object>());
			val2.m_description = GcLoc.Get("gcld_desc", Array.Empty<object>());
			val2.m_icon = icon;
			PieceConfig val3 = new PieceConfig();
			val3.PieceTable = "_HammerPieceTable";
			val3.Category = "Misc";
			val3.CraftingStation = "piece_workbench";
			val3.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig("Wood", PieceCost, 0, true)
			};
			PieceConfig val4 = val3;
			PieceManager.Instance.AddPiece(new CustomPiece(val, true, val4));
			GameObject val5 = Build("GC_Ladder", "wood_pole2", prefab, 2f);
			if ((Object)(object)val5 != (Object)null)
			{
				Piece val6 = (OldLadderPiece = val5.GetComponent<Piece>());
				val6.m_name = val2.m_name;
				val6.m_description = val2.m_description;
				val6.m_icon = icon;
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("Wood");
				ItemDrop val7 = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val7 != (Object)null)
				{
					val6.m_resources = (Requirement[])(object)new Requirement[1]
					{
						new Requirement
						{
							m_resItem = val7,
							m_amount = WoodCost.Value,
							m_recover = true
						}
					};
				}
				PrefabManager.Instance.AddPrefab(new CustomPrefab(val5, true));
			}
		}

		private static GameObject? Build(string name, string poleName, GameObject rungSource, float fallbackHeight)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00fc: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Expected O, but got Unknown
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_0546: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Expected O, but got Unknown
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_0576: Unknown result type (might be due to invalid IL or missing references)
			//IL_0584: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(name, poleName);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)(poleName + " nicht gefunden, Leiter " + name + " wird nicht erstellt."));
				return null;
			}
			LogHierarchy(val.transform, poleName);
			Transform transform = val.transform;
			Bounds val2 = (Bounds)(((??)SnapBounds(transform)) ?? new Bounds(new Vector3(0f, fallbackHeight * 0.5f, 0f), new Vector3(0.2f, fallbackHeight, 0.2f)));
			float y = ((Bounds)(ref val2)).size.y;
			LODGroup component = val.GetComponent<LODGroup>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			List<Transform> list = new List<Transform>();
			foreach (Transform item2 in transform)
			{
				Transform item = item2;
				list.Add(item);
			}
			float num = 0f - ((Bounds)(ref val2)).min.y;
			foreach (Transform item3 in list)
			{
				item3.localPosition += Vector3.up * num;
			}
			Transform val3 = transform.Find("New");
			Bounds? val4 = (((Object)(object)val3 != (Object)null) ? BoundsIn(val3, transform) : ((Bounds?)null)) ?? BoundsIn(transform, transform);
			float num2;
			if (!val4.HasValue)
			{
				num2 = 0f;
			}
			else
			{
				Bounds value = val4.Value;
				float x = ((Bounds)(ref value)).size.x;
				value = val4.Value;
				num2 = Mathf.Max(x, ((Bounds)(ref value)).size.z);
			}
			float num3 = num2;
			float num4 = ((num3 > 0.02f) ? Mathf.Clamp(0.09f / num3, 0.05f, 1.5f) : 1f);
			GameObject val5 = new GameObject("rail_L");
			val5.transform.SetParent(transform, false);
			foreach (Transform item4 in list)
			{
				if (!((Component)item4).CompareTag("snappoint"))
				{
					item4.SetParent(val5.transform, true);
				}
			}
			val5.transform.localScale = new Vector3(num4, 1f, num4);
			val5.transform.localPosition = new Vector3(-0.3f, 0f, 0f);
			GameObject val6 = Object.Instantiate<GameObject>(val5, transform, false);
			((Object)val6).name = "rail_R";
			val6.transform.localPosition = new Vector3(0.3f, 0f, 0f);
			Transform[] componentsInChildren = val6.GetComponentsInChildren<Transform>(true);
			foreach (Transform val7 in componentsInChildren)
			{
				if ((Object)(object)val7 != (Object)(object)val6.transform && ((Object)val7).name.Contains("snow"))
				{
					Object.DestroyImmediate((Object)(object)((Component)val7).gameObject);
					break;
				}
			}
			Collider[] components = val.GetComponents<Collider>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			Transform val8 = rungSource.transform.Find("New");
			int num5 = 0;
			if ((Object)(object)val8 != (Object)null)
			{
				num5 = Mathf.Max(2, Mathf.RoundToInt(y / 0.33f));
				float num6 = y / (float)num5;
				Bounds? val9 = BoundsIn(val8, rungSource.transform);
				Quaternion val10 = Quaternion.identity;
				Vector3 one = Vector3.one;
				Vector3 localPosition = Vector3.zero;
				if (val9.HasValue)
				{
					Bounds value2 = val9.Value;
					Vector3 val11 = default(Vector3);
					((Vector3)(ref val11))..ctor(Mathf.Max(0.001f, ((Bounds)(ref value2)).size.x), Mathf.Max(0.001f, ((Bounds)(ref value2)).size.y), Mathf.Max(0.001f, ((Bounds)(ref value2)).size.z));
					int num7 = ((val11.y >= val11.x && val11.y >= val11.z) ? 1 : ((val11.z >= val11.x) ? 2 : 0));
					val10 = (Quaternion)(num7 switch
					{
						2 => Quaternion.Euler(0f, 90f, 0f), 
						1 => Quaternion.Euler(0f, 0f, 90f), 
						_ => Quaternion.identity, 
					});
					float num8 = 0.69000006f;
					((Vector3)(ref one))..ctor(((num7 == 0) ? num8 : 0.05f) / val11.x, ((num7 == 1) ? num8 : 0.05f) / val11.y, ((num7 == 2) ? num8 : 0.05f) / val11.z);
					localPosition = -(val10 * Vector3.Scale(((Bounds)(ref value2)).center, one));
				}
				for (int j = 0; j < num5; j++)
				{
					GameObject val12 = new GameObject("rung_" + j);
					val12.transform.SetParent(transform, false);
					val12.transform.localPosition = new Vector3(0f, num6 * ((float)j + 0.5f), 0f);
					GameObject val13 = new GameObject("shape");
					val13.transform.SetParent(val12.transform, false);
					val13.transform.localRotation = val10;
					val13.transform.localScale = one;
					val13.transform.localPosition = localPosition;
					components = Object.Instantiate<GameObject>(((Component)val8).gameObject, val13.transform, false).GetComponentsInChildren<Collider>(true);
					for (int i = 0; i < components.Length; i++)
					{
						Object.DestroyImmediate((Object)(object)components[i]);
					}
				}
			}
			else
			{
				Log.LogWarning((object)"Modell 'New' in wood_pole nicht gefunden, Leiter ohne Sprossen.");
			}
			BoxCollider obj = val.AddComponent<BoxCollider>();
			obj.center = new Vector3(0f, y * 0.5f, 0f);
			obj.size = new Vector3(0.69000006f, y, 0.12f);
			LadderClimb ladderClimb = val.AddComponent<LadderClimb>();
			ladderClimb.m_bottom = 0f;
			ladderClimb.m_top = y;
			Log.LogInfo((object)$"Leiter {name} erstellt: Höhe {y:F2} m, {num5} Sprossen, Holme {num3:F2} m → ×{num4:F2}.");
			return val;
		}

		private static Bounds? BoundsIn(Transform model, Transform space)
		{
			//IL_0009: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Bounds? result = null;
			Matrix4x4 worldToLocalMatrix = space.worldToLocalMatrix;
			MeshFilter[] componentsInChildren = ((Component)model).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val.sharedMesh != (Object)null)
				{
					Encapsulate(ref result, val.sharedMesh.bounds, worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix);
				}
			}
			if (!result.HasValue)
			{
				BoxCollider[] componentsInChildren2 = ((Component)model).GetComponentsInChildren<BoxCollider>(true);
				foreach (BoxCollider val2 in componentsInChildren2)
				{
					Encapsulate(ref result, new Bounds(val2.center, val2.size), worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix);
				}
			}
			return result;
		}

		private static void Encapsulate(ref Bounds? result, Bounds local, Matrix4x4 matrix)
		{
			//IL_0002: 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: 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_0026: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref local)).min;
			Vector3 max = ((Bounds)(ref local)).max;
			Vector3 val = default(Vector3);
			for (int i = 0; i < 8; i++)
			{
				((Vector3)(ref val))..ctor(((i & 1) == 0) ? min.x : max.x, ((i & 2) == 0) ? min.y : max.y, ((i & 4) == 0) ? min.z : max.z);
				Vector3 val2 = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(val);
				if (!result.HasValue)
				{
					result = new Bounds(val2, Vector3.zero);
					continue;
				}
				Bounds value = result.Value;
				((Bounds)(ref value)).Encapsulate(val2);
				result = value;
			}
		}

		internal static void ApplyEnabled()
		{
			if (!((Object)(object)LadderPiece == (Object)null) && LadderPiece.m_enabled != On)
			{
				LadderPiece.m_enabled = On;
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					Player.m_localPlayer.UpdateAvailablePiecesList();
				}
			}
		}

		internal static void ApplyCost()
		{
			if (!((Object)(object)LadderPiece == (Object)null) && LadderPiece.m_resources != null)
			{
				if (LadderPiece.m_resources.Length == 1)
				{
					LadderPiece.m_resources[0].m_amount = PieceCost;
				}
				if ((Object)(object)OldLadderPiece != (Object)null && OldLadderPiece.m_resources != null && OldLadderPiece.m_resources.Length == 1)
				{
					OldLadderPiece.m_resources[0].m_amount = WoodCost.Value;
				}
			}
		}

		private static Bounds? SnapBounds(Transform root)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Component)val).CompareTag("snappoint"))
				{
					list.Add(root.InverseTransformPoint(val.position));
				}
			}
			if (list.Count < 2)
			{
				return null;
			}
			float num = list.Min((Vector3 p) => p.y);
			float num2 = list.Max((Vector3 p) => p.y);
			if (num2 - num < 0.5f)
			{
				return null;
			}
			return new Bounds(new Vector3(0f, (num + num2) * 0.5f, 0f), new Vector3(0.2f, num2 - num, 0.2f));
		}

		private static void LogHierarchy(Transform root, string label)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				string text = string.Join(",", from c in ((Component)val).GetComponents<Component>()
					select ((object)c).GetType().Name);
				Log.LogDebug((object)$"Leiter-Aufbau [{label}] {((Object)val).name} tag={((Component)val).tag} pos={root.InverseTransformPoint(val.position)} {text}");
			}
		}

		private static Sprite LadderIcon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.62f, 0.42f, 0.22f, 1f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.3f, 0.18f, 0.08f, 1f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					bool num = (j >= 14 && j <= 20) || (j >= 43 && j <= 49);
					bool flag = j > 20 && j < 43 && i % 12 >= 4 && i % 12 <= 7;
					Color val5 = ((num || flag) ? val3 : val2);
					if ((num && (j == 14 || j == 20 || j == 43 || j == 49)) || (flag && (i % 12 == 4 || i % 12 == 7)))
					{
						val5 = val4;
					}
					val.SetPixel(j, i, val5);
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}
	}
	public class LadderClimb : MonoBehaviour, Interactable, Hoverable
	{
		public float m_bottom;

		public float m_top = 2f;

		private static readonly List<LadderClimb> All = new List<LadderClimb>();

		private static readonly Collider[] Hits = (Collider[])(object)new Collider[16];

		private static int mask;

		private Vector3 Bottom => ((Component)this).transform.TransformPoint(new Vector3(0f, m_bottom, 0f));

		private Vector3 Top => ((Component)this).transform.TransformPoint(new Vector3(0f, m_top, 0f));

		private static int Mask
		{
			get
			{
				if (mask == 0)
				{
					return mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
				}
				return mask;
			}
		}

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

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

		private LadderClimb? Neighbour(bool up)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_003d: 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_004b: 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)
			Vector3 val = (up ? Top : Bottom);
			foreach (LadderClimb item in All)
			{
				if (!((Object)(object)item == (Object)(object)this) && !((Object)(object)item == (Object)null))
				{
					Vector3 val2 = (up ? item.Bottom : item.Top);
					if (Vector3.Distance(val, val2) < 0.45f)
					{
						return item;
					}
				}
			}
			return null;
		}

		private LadderClimb End(bool up)
		{
			LadderClimb ladderClimb = this;
			HashSet<LadderClimb> hashSet = new HashSet<LadderClimb> { this };
			while (true)
			{
				LadderClimb ladderClimb2 = ladderClimb.Neighbour(up);
				if ((Object)(object)ladderClimb2 == (Object)null || !hashSet.Add(ladderClimb2))
				{
					break;
				}
				ladderClimb = ladderClimb2;
			}
			return ladderClimb;
		}

		private bool GoesUp(Humanoid user, bool alt, LadderClimb top, LadderClimb bottom)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (alt)
			{
				return false;
			}
			float y = ((Component)user).transform.position.y;
			if ((Object)(object)this == (Object)(object)top && (Object)(object)this != (Object)(object)bottom && y > Bottom.y + 0.5f)
			{
				return false;
			}
			if ((Object)(object)this == (Object)(object)bottom && (Object)(object)this != (Object)(object)top && y < Top.y - 0.5f)
			{
				return true;
			}
			return y < (top.Top.y + bottom.Bottom.y) * 0.5f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer || !Plugin.On)
			{
				return false;
			}
			LadderClimb ladderClimb = End(up: true);
			LadderClimb ladderClimb2 = End(up: false);
			Vector3 top = ladderClimb.Top;
			Vector3 bottom = ladderClimb2.Bottom;
			bool num = GoesUp(user, alt, ladderClimb, ladderClimb2);
			float value = Plugin.ExitDistance.Value;
			Vector3 val = ladderClimb2.FrontOf(top, bottom, value, user);
			Vector3 position = (Vector3)((!num) ? (((??)Spot(bottom + val * value, 2.5f, user)) ?? ((??)Spot(bottom - val * value, 2.5f, user)) ?? ((??)Ground(bottom + val * value, 2.5f)) ?? (bottom + val * value)) : (((??)Spot(top - val * value, 1.6f, user)) ?? ((??)Spot(top + val * value, 1.6f, user)) ?? ((??)Ground(top - val * value, 1.6f)) ?? (top + Vector3.up * 0.2f)));
			((Component)user).transform.position = position;
			Rigidbody component = ((Component)user).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.position = position;
				component.linearVelocity = Vector3.zero;
			}
			Physics.SyncTransforms();
			return false;
		}

		private Vector3 FrontOf(Vector3 topPoint, Vector3 bottomPoint, float distance, Humanoid user)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.forward;
			val.y = 0f;
			val = ((((Vector3)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			bool hasValue = Spot(bottomPoint + val * distance, 2.5f, user).HasValue;
			bool hasValue2 = Spot(bottomPoint - val * distance, 2.5f, user).HasValue;
			if (hasValue != hasValue2)
			{
				if (!hasValue)
				{
					return -val;
				}
				return val;
			}
			bool hasValue3 = Spot(topPoint + val * distance, 1.6f, user).HasValue;
			bool hasValue4 = Spot(topPoint - val * distance, 1.6f, user).HasValue;
			if (hasValue3 != hasValue4)
			{
				if (!hasValue4)
				{
					return -val;
				}
				return val;
			}
			return val;
		}

		private static Vector3? Spot(Vector3 point, float depth, Humanoid user)
		{
			//IL_0000: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Vector3? val = Ground(point, depth);
			if (!val.HasValue)
			{
				return null;
			}
			Vector3 value = val.Value;
			int num = Physics.OverlapCapsuleNonAlloc(value + Vector3.up * 0.6f, value + Vector3.up * 1.5f, 0.3f, Hits, Mask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num; i++)
			{
				Collider val2 = Hits[i];
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).GetComponentInParent<LadderClimb>() != (Object)null) && !((Object)(object)((Component)val2).GetComponentInParent<Character>() != (Object)null))
				{
					return null;
				}
			}
			return value;
		}

		private static Vector3? Ground(Vector3 point, float depth)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(point + Vector3.up * 1.2f, Vector3.down, ref val, 1.2f + depth, Mask, (QueryTriggerInteraction)1))
			{
				if ((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<LadderClimb>() != (Object)null)
				{
					return null;
				}
				return ((RaycastHit)(ref val)).point + Vector3.up * 0.05f;
			}
			return null;
		}

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

		public string GetHoverText()
		{
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && GoesUp((Humanoid)(object)localPlayer, alt: false, End(up: true), End(up: false));
			string text = GcLoc.Get("gcld_name", Array.Empty<object>()) + "\n[<color=yellow><b>$KEY_Use</b></color>] " + GcLoc.Get(flag ? "gcld_up" : "gcld_down", Array.Empty<object>());
			if (flag)
			{
				text = text + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] " + GcLoc.Get("gcld_down", Array.Empty<object>());
			}
			return Localization.instance.Localize(text);
		}

		public string GetHoverName()
		{
			return GcLoc.Get("gcld_name", Array.Empty<object>());
		}

		public float GetHoverOffset()
		{
			return 0f;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Parade.dll

Decompiled 4 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Deflect;
using GC.Shared;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Parade")]
[assembly: AssemblyTitle("GC_Parade")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModParade
{
	[BepInPlugin("gorduan.gc.parade", "GC_Parade", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.parade");
			GC.Server.Deflect.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			Module.TakeOverOldSettings();
			Module.IsOn = () => GC.Server.Deflect.Plugin.On;
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("deflect", (ConfigEntryBase)(object)GC.Server.Deflect.Plugin.Enabled, (Func<bool>)(() => GC.Server.Deflect.Plugin.Blocked), "GC_Deflect", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("deflect_arrows", (ConfigEntryBase)(object)GC.Server.Deflect.Plugin.DeflectArrows, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("deflect_damage", (ConfigEntryBase)(object)GC.Server.Deflect.Plugin.DamageFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}
	}
	internal static class GcMod
	{
		public const string Id = "parade";

		public const string Guid = "gorduan.gc.parade";

		public const string Name = "GC_Parade";

		public const string Version = "1.8.1";

		public const int Stufe = 4;

		public static GcModInfo Info => new GcModInfo
		{
			Id = "parade",
			Guid = "gorduan.gc.parade",
			Name = "GC_Parade",
			Version = "1.8.1",
			Stufe = 4,
			Seite = (GcSeite)2,
			Braucht = Array.Empty<string>(),
			Partner = Array.Empty<string>(),
			Fremd = Array.Empty<string>(),
			AlteConfig = "gorduan.gc_server.cfg",
			Ausgleich = 2f
		};
	}
}
namespace GC.Server.Deflect
{
	internal static class Plugin
	{
		public const string Guid = "gorduan.gc_deflect";

		public const string ModName = "GC_Deflect";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> DamageFactor;

		internal static ConfigEntry<float> FallbackSpeed;

		internal static ConfigEntry<string> ExtraAllowed;

		internal static ConfigEntry<string> NeverList;

		internal static ConfigEntry<bool> DeflectArrows;

		internal static ConfigEntry<bool> LogProjectiles;

		internal static bool Blocked => Chainloader.PluginInfos.ContainsKey("gorduan.gc_deflect");

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return !Blocked;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "3 - Deflect", "Enabled", true, "Funktion ein- oder ausschalten (wird vom Server vorgegeben, auch im Menü GC Option).", (AcceptableValueBase)null);
			DamageFactor = Gc.BindSynced<float>(Config, "3 - Deflect", "DamageFactor", 1f, "Schaden des zurückgeworfenen Geschosses relativ zum Originalschaden.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f));
			FallbackSpeed = Gc.BindSynced<float>(Config, "3 - Deflect", "FallbackSpeed", 25f, "Fluggeschwindigkeit in m/s, falls die Originalgeschwindigkeit unbekannt ist.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 80f));
			ExtraAllowed = Gc.BindSynced<string>(Config, "3 - Deflect - Filter", "AlwaysDeflect", "", "Kommagetrennte Geschoss-Prefabs, die immer zurückgeworfen werden (auch wenn sie nicht als fest erkannt werden).", (AcceptableValueBase)null);
			NeverList = Gc.BindSynced<string>(Config, "3 - Deflect - Filter", "NeverDeflect", "", "Kommagetrennte Geschoss-Prefabs, die nie zurückgeworfen werden.", (AcceptableValueBase)null);
			DeflectArrows = Gc.BindSynced<bool>(Config, "3 - Deflect - Filter", "DeflectArrows", true, "Pfeile und Bolzen immer zurückwerfen, auch mit Feuer, Gift oder Frost (Bogen- und Armbrust-Schüsse).", (AcceptableValueBase)null);
			LogProjectiles = Gc.Bind<bool>(Config, "3 - Deflect - Debug", "LogProjectiles", false, "Bei jeder perfekten Parade gegen ein Geschoss den Prefab-Namen ins Log schreiben (für die Filterlisten).", (AcceptableValueBase)null);
		}

		internal static bool IsSolid(Projectile projectile, string prefabName, SkillType skill)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (Gc.ParseList(NeverList.Value).Contains(prefabName))
			{
				return false;
			}
			if (Gc.ParseList(ExtraAllowed.Value).Contains(prefabName))
			{
				return true;
			}
			if (DeflectArrows.Value && ((int)skill == 8 || (int)skill == 14))
			{
				return true;
			}
			DamageTypes damage = projectile.m_damage;
			bool flag = damage.m_fire > 0f || damage.m_frost > 0f || damage.m_lightning > 0f || damage.m_poison > 0f || damage.m_spirit > 0f;
			if ((damage.m_blunt > 0f || damage.m_slash > 0f || damage.m_pierce > 0f || damage.m_chop > 0f || damage.m_pickaxe > 0f) && !flag)
			{
				return string.IsNullOrEmpty(projectile.m_statusEffect);
			}
			return false;
		}

		internal static Vector3 Aim(Vector3 from, Vector3 to, float speed, float gravity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = to - from;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(val.x, 0f, val.z);
			float magnitude = ((Vector3)(ref val2)).magnitude;
			float y = val.y;
			if (gravity <= 0.01f || magnitude < 0.1f)
			{
				return ((Vector3)(ref val)).normalized * speed;
			}
			float num = speed * speed;
			float num2 = num * num - gravity * (gravity * magnitude * magnitude + 2f * y * num);
			float num3 = ((num2 < 0f) ? ((float)Math.PI / 4f) : Mathf.Atan((num - Mathf.Sqrt(num2)) / (gravity * magnitude)));
			return (((Vector3)(ref val2)).normalized * Mathf.Cos(num3) + Vector3.up * Mathf.Sin(num3)) * speed;
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class ProjectileOnHitPatch
	{
		internal const string Rpc = "GC_Deflect_Info";

		internal static Projectile? Current;

		internal static string RemotePrefab = "";

		internal static Vector3 RemoteVelocity;

		internal static float RemoteTime = -10f;

		private static void Prefix(Projectile __instance, Collider collider)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			Current = __instance;
			if (!Plugin.On || (Object)(object)collider == (Object)null || ZRoutedRpc.instance == null)
			{
				return;
			}
			GameObject val = Projectile.FindHitObject(collider);
			Player val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Player>() : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)Player.m_localPlayer) && !((Object)(object)((Character)val2).m_nview == (Object)null) && ((Character)val2).m_nview.IsValid())
			{
				long owner = ((Character)val2).m_nview.GetZDO().GetOwner();
				if (owner != 0L && owner != ZNet.GetUID())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(owner, "GC_Deflect_Info", new object[2]
					{
						Utils.GetPrefabName(((Component)__instance).gameObject),
						__instance.m_vel
					});
				}
			}
		}

		private static void Finalizer()
		{
			Current = null;
		}

		internal static void OnInfo(long sender, string prefab, Vector3 velocity)
		{
			//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)
			RemotePrefab = prefab;
			RemoteVelocity = velocity;
			RemoteTime = Time.time;
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class GameStartPatch
	{
		private static void Postfix()
		{
			if (!Plugin.Blocked)
			{
				ZRoutedRpc.instance.Register<string, Vector3>("GC_Deflect_Info", (Action<long, string, Vector3>)ProjectileOnHitPatch.OnInfo);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
	internal static class BlockAttackPatch
	{
		private struct State
		{
			public bool Perfect;

			public DamageTypes Damage;

			public float Blockable;
		}

		private static float lastDeflect;

		private static void Prefix(Humanoid __instance, HitData hit, out State __state)
		{
			//IL_008a: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			__state = default(State);
			if (Plugin.On && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && hit.m_ranged)
			{
				ItemData currentBlocker = __instance.GetCurrentBlocker();
				__state.Perfect = currentBlocker != null && currentBlocker.m_shared.m_timedBlockBonus > 1f && __instance.m_blockTimer != -1f && __instance.m_blockTimer < 0.25f && Vector3.Dot(hit.m_dir, ((Component)__instance).transform.forward) <= 0f;
				__state.Damage = ((DamageTypes)(ref hit.m_damage)).Clone();
				__state.Blockable = hit.GetTotalBlockableDamage();
			}
		}

		private static void Postfix(Humanoid __instance, HitData hit, Character attacker, State __state)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_01b9: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Expected O, but got Unknown
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			if (!__state.Perfect || (Object)(object)attacker == (Object)null || attacker.IsDead() || Time.time - lastDeflect < 0.15f)
			{
				return;
			}
			Player val = (Player)__instance;
			if (__state.Blockable > 0f && hit.GetTotalBlockableDamage() >= __state.Blockable - 0.01f)
			{
				return;
			}
			GameObject val2 = null;
			float speed = Plugin.FallbackSpeed.Value;
			Projectile current = ProjectileOnHitPatch.Current;
			if ((Object)(object)current != (Object)null)
			{
				val2 = ZNetScene.instance.GetPrefab(Utils.GetPrefabName(((Component)current).gameObject));
				speed = Mathf.Max(5f, ((Vector3)(ref current.m_vel)).magnitude);
			}
			else if (Time.time - ProjectileOnHitPatch.RemoteTime < 1.5f && ProjectileOnHitPatch.RemotePrefab.Length > 0)
			{
				val2 = ZNetScene.instance.GetPrefab(ProjectileOnHitPatch.RemotePrefab);
				speed = Mathf.Max(5f, ((Vector3)(ref ProjectileOnHitPatch.RemoteVelocity)).magnitude);
				ProjectileOnHitPatch.RemoteTime = -10f;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Humanoid val3 = (Humanoid)(object)((attacker is Humanoid) ? attacker : null);
				if (val3 != null)
				{
					Attack val4 = val3.m_currentAttack ?? val3.m_previousAttack;
					if ((Object)(object)val4?.m_attackProjectile != (Object)null)
					{
						val2 = val4.m_attackProjectile;
						speed = Mathf.Max(5f, val4.m_projectileVel);
					}
				}
			}
			Projectile val5 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Projectile>() : null);
			if (!((Object)(object)val5 == (Object)null))
			{
				string name = ((Object)val2).name;
				if (Plugin.LogProjectiles.Value)
				{
					Plugin.Log.LogInfo((object)("Perfekte Parade gegen Geschoss '" + name + "' von " + attacker.m_name + "."));
				}
				if (Plugin.IsSolid(val5, name, hit.m_skill))
				{
					lastDeflect = Time.time;
					Vector3 centerPoint = attacker.GetCenterPoint();
					Vector3 point = hit.m_point;
					Vector3 val6 = centerPoint - hit.m_point;
					Vector3 val7 = point + ((Vector3)(ref val6)).normalized * 0.8f + Vector3.up * 0.3f;
					Vector3 val8 = Plugin.Aim(val7, centerPoint, speed, val5.m_gravity);
					HitData val9 = new HitData
					{
						m_damage = __state.Damage,
						m_pushForce = 30f,
						m_blockable = true,
						m_dodgeable = true,
						m_skill = (SkillType)6,
						m_hitType = (HitType)2
					};
					((DamageTypes)(ref val9.m_damage)).Modify(Plugin.DamageFactor.Value);
					Object.Instantiate<GameObject>(val2, val7, Quaternion.LookRotation(val8)).GetComponent<Projectile>().Setup((Character)(object)val, val8, -1f, val9, (ItemData)null, (ItemData)null);
					Gc.TopLeft(GcLoc.Get("gcd_deflected", Array.Empty<object>()));
				}
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Portalnamen.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Client;
using GC.Client.PortalNames;
using GC.Server;
using GC.Server.PortalNames;
using GC.Shared;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Portalnamen")]
[assembly: AssemblyTitle("GC_Portalnamen")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.PortalNames
{
	public enum Editors
	{
		Admins,
		Everyone
	}
	internal static class Plugin
	{
		internal const string RpcRequest = "GC_PortalNames_Request";

		internal const string RpcEdit = "GC_PortalNames_Edit";

		internal const string RpcList = "GC_PortalNames_List";

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<Editors> EditBy = null;

		private static readonly List<string> Stored = new List<string>();

		private static string? loadedFile;

		private static List<string> received = new List<string>();

		private static bool haveList;

		private static int version;

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return ServerPlugin.OnServer;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "6 - Portal Names", "Enabled", true, "Gemeinsame Server-Liste der Portalnamen für den Portal-Dialog von GC_Client (wird vom Server vorgegeben).", (AcceptableValueBase)null);
			EditBy = Gc.BindSynced<Editors>(Config, "6 - Portal Names", "EditBy", Editors.Admins, "Wer die Server-Liste bearbeiten darf: Admins oder Everyone (alle Spieler).", (AcceptableValueBase)null);
			GcPortalNames.Register("server", 10, (Func<string>)(() => GcLoc.Get("gcsv_pn_title", Array.Empty<object>())), (Func<bool>)(() => On && haveList), (Func<List<string>>)(() => new List<string>(received)), (Func<bool>)CanEditLocal, (Action<string>)delegate(string name)
			{
				Send(add: true, name);
			}, (Action<string>)delegate(string name)
			{
				Send(add: false, name);
			}, (Action)Request, (Func<int>)(() => version));
		}

		private static bool CanEditLocal()
		{
			if (On && (Object)(object)ZNet.instance != (Object)null)
			{
				if (EditBy.Value != Editors.Everyone)
				{
					return GcMenu.CanChangeServer;
				}
				return true;
			}
			return false;
		}

		private static void Request()
		{
			if (On && ZRoutedRpc.instance != null && (Object)(object)ZNet.instance != (Object)null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC("GC_PortalNames_Request", Array.Empty<object>());
			}
		}

		private static void Send(bool add, string name)
		{
			if (CanEditLocal() && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC("GC_PortalNames_Edit", new object[2]
				{
					add,
					GcPortalNames.Clean(name)
				});
			}
		}

		internal static void ResetClient()
		{
			received = new List<string>();
			haveList = false;
			version++;
		}

		internal static void OnList(long sender, ZPackage pkg)
		{
			int num = pkg.ReadInt();
			List<string> list = new List<string>(num);
			for (int i = 0; i < num; i++)
			{
				list.Add(pkg.ReadString());
			}
			received = list;
			haveList = true;
			version++;
		}

		internal static void OnRequest(long sender)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && On)
			{
				EnsureLoaded();
				SendList(sender);
			}
		}

		internal static void OnEdit(long sender, bool add, string name)
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !On)
			{
				return;
			}
			if (!MayEdit(sender))
			{
				Log.LogWarning((object)$"Portalnamen: Änderung von {sender} abgelehnt (keine Rechte).");
				return;
			}
			EnsureLoaded();
			string text = GcPortalNames.Clean(name);
			if (!(add ? (!Stored.Contains(text)) : Stored.Contains(text)))
			{
				SendList(sender);
				return;
			}
			if (add && Stored.Count >= 200)
			{
				SendList(sender);
				return;
			}
			if (add)
			{
				Stored.Add(text);
			}
			else
			{
				Stored.Remove(text);
			}
			List<string> collection = GcPortalNames.Normalize((IEnumerable<string>)Stored);
			Stored.Clear();
			Stored.AddRange(collection);
			Save();
			Log.LogInfo((object)string.Format("Portalnamen: '{0}' {1} von {2}.", text, add ? "hinzugefügt" : "entfernt", sender));
			SendList(0L);
		}

		private static bool MayEdit(long sender)
		{
			if (EditBy.Value == Editors.Everyone || (sender == ZNet.GetUID() && !ZNet.instance.IsDedicated()))
			{
				return true;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			if (peer != null && peer.m_socket != null)
			{
				return ZNet.instance.IsAdmin(peer.m_socket.GetHostName());
			}
			return false;
		}

		private static void SendList(long target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(Stored.Count);
			foreach (string item in Stored)
			{
				val.Write(item);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(target, "GC_PortalNames_List", new object[1] { val });
		}

		private static string FileName()
		{
			string text = ((ZNet.World != null && !string.IsNullOrEmpty(ZNet.World.m_name)) ? ZNet.World.m_name : "world");
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char oldChar in invalidFileNameChars)
			{
				text = text.Replace(oldChar, '_');
			}
			return Path.Combine(Path.Combine(Paths.ConfigPath, "GC_Server"), "portalnames_" + text + ".txt");
		}

		private static void EnsureLoaded()
		{
			string text = FileName();
			if (loadedFile == text)
			{
				return;
			}
			loadedFile = text;
			Stored.Clear();
			try
			{
				if (File.Exists(text))
				{
					Stored.AddRange(GcPortalNames.Normalize((IEnumerable<string>)File.ReadAllLines(text, Encoding.UTF8)));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Portalnamen konnten nicht gelesen werden (" + text + "): " + ex.Message));
			}
		}

		private static void Save()
		{
			try
			{
				string path = FileName();
				Directory.CreateDirectory(Path.GetDirectoryName(path));
				File.WriteAllLines(path, Stored, Encoding.UTF8);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Portalnamen konnten nicht gespeichert werden: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class GameStartPatch
	{
		private static void Postfix()
		{
			Plugin.ResetClient();
			ZRoutedRpc.instance.Register("GC_PortalNames_Request", (Action<long>)Plugin.OnRequest);
			ZRoutedRpc.instance.Register<bool, string>("GC_PortalNames_Edit", (Action<long, bool, string>)Plugin.OnEdit);
			ZRoutedRpc.instance.Register<ZPackage>("GC_PortalNames_List", (Action<long, ZPackage>)Plugin.OnList);
		}
	}
}
namespace GC.Mods.Portalnamen
{
	[BepInPlugin("gorduan.gc.portalnamen", "GC_Portalnamen", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ClientPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ClientPlugin.Module = Module;
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.portalnamen");
			GC.Client.PortalNames.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			GC.Server.PortalNames.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			Module.TakeOverOldSettings();
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gccm_" + key, Array.Empty<object>())), (string)null).Main("portalnames", (ConfigEntryBase)(object)GC.Client.PortalNames.Plugin.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("portalnames_click", (ConfigEntryBase)(object)GC.Client.PortalNames.Plugin.ClickRenames, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), "gck_mod_portalnamen_server").Main("portalnames", (ConfigEntryBase)(object)GC.Server.PortalNames.Plugin.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("portalnames_editors", (ConfigEntryBase)(object)GC.Server.PortalNames.Plugin.EditBy, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}

		private void Update()
		{
			if (!Gc.IsHeadless)
			{
				Module.Guard("Portalnamen", (Action)GC.Client.PortalNames.Plugin.Update);
			}
		}
	}
	internal static class GcMod
	{
		public const string Id = "portalnamen";

		public const string Guid = "gorduan.gc.portalnamen";

		public const string Name = "GC_Portalnamen";

		public const string Version = "1.8.1";

		public const int Stufe = 1;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "portalnamen";
				val.Guid = "gorduan.gc.portalnamen";
				val.Name = "GC_Portalnamen";
				val.Version = "1.8.1";
				val.Stufe = 1;
				val.Seite = (GcSeite)1;
				val.Braucht = Array.Empty<string>();
				val.Partner = new string[1] { "portalschutz" };
				val.Fremd = Array.Empty<string>();
				val.AlteConfig = "gorduan.gc_client.cfg;gorduan.gc_server.cfg";
				val.Ausgleich = 0f;
				return val;
			}
		}
	}
}
namespace GC.Client
{
	internal static class ClientPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Client.PortalNames
{
	internal static class Plugin
	{
		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<bool> ClickRenames = null;

		private static readonly List<string> Own = new List<string>();

		private static int ownVersion;

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return ClientPlugin.Allowed;
				}
				return false;
			}
		}

		private static string FilePath => Path.Combine(Paths.ConfigPath, "gorduan.gc_client.portalnames.txt");

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ClientPlugin.Log;
			Enabled = Gc.Bind<bool>(Config, "10 - PortalNames", "Enabled", true, "Liste gemerkter Portalnamen neben dem Umbenennen-Dialog.", (AcceptableValueBase)null);
			ClickRenames = Gc.Bind<bool>(Config, "10 - PortalNames", "ClickRenames", true, "Klick auf einen Namen benennt das Portal sofort um. Aus = der Name wird nur ins Eingabefeld geschrieben.", (AcceptableValueBase)null);
			LoadOwn();
			GcPortalNames.Register("own", 0, (Func<string>)(() => GcLoc.Get("gcpn_own", Array.Empty<object>())), (Func<bool>)(() => true), (Func<List<string>>)(() => new List<string>(Own)), (Func<bool>)(() => true), (Action<string>)AddOwn, (Action<string>)RemoveOwn, (Action)delegate
			{
			}, (Func<int>)(() => ownVersion));
		}

		internal static void Update()
		{
			PortalNameWindow.Tick();
		}

		private static void LoadOwn()
		{
			try
			{
				if (File.Exists(FilePath))
				{
					Own.Clear();
					Own.AddRange(GcPortalNames.Normalize((IEnumerable<string>)File.ReadAllLines(FilePath, Encoding.UTF8)));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Portalnamen-Liste konnte nicht gelesen werden: " + ex.Message));
			}
		}

		private static void SaveOwn()
		{
			try
			{
				File.WriteAllLines(FilePath, Own, Encoding.UTF8);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Portalnamen-Liste konnte nicht gespeichert werden: " + ex.Message));
			}
			ownVersion++;
		}

		private static void AddOwn(string name)
		{
			string item = GcPortalNames.Clean(name);
			if (!Own.Contains(item))
			{
				Own.Add(item);
				List<string> collection = GcPortalNames.Normalize((IEnumerable<string>)Own);
				Own.Clear();
				Own.AddRange(collection);
				SaveOwn();
			}
		}

		private static void RemoveOwn(string name)
		{
			if (Own.Remove(name))
			{
				SaveOwn();
			}
		}
	}
	internal static class PortalNameWindow
	{
		private static GameObject? panel;

		private static RectTransform? content;

		private static TeleportWorld? openedFor;

		private static string signature = "";

		internal static void Tick()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			TextInput instance = TextInput.instance;
			if (!Plugin.On || Gc.IsHeadless || !((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_panel != (Object)null) || !instance.m_panel.activeSelf || !(instance.m_queuedSign is TeleportWorld))
			{
				if ((Object)(object)panel != (Object)null && panel.activeSelf)
				{
					panel.SetActive(false);
				}
				openedFor = null;
			}
			else
			{
				if ((Object)(object)panel == (Object)null && !Build())
				{
					return;
				}
				TeleportWorld val = (TeleportWorld)instance.m_queuedSign;
				if (!panel.activeSelf)
				{
					panel.SetActive(true);
					panel.transform.SetAsLastSibling();
				}
				if ((Object)(object)openedFor != (Object)(object)val)
				{
					openedFor = val;
					foreach (Dictionary<string, object> item in Providers())
					{
						((Action)item["refresh"])();
					}
					signature = "";
				}
				string text = Signature();
				if (text != signature)
				{
					signature = text;
					Fill();
				}
			}
		}

		private static List<Dictionary<string, object>> Providers()
		{
			List<object> list = GcPortalNames.Providers();
			lock (list)
			{
				return (from p in list.OfType<Dictionary<string, object>>()
					orderby (int)p["order"]
					select p).ToList();
			}
		}

		private static string Signature()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(Previous(out var _)).Append('|');
			foreach (Dictionary<string, object> item in Providers())
			{
				stringBuilder.Append(item["id"]).Append(':').Append(((Func<bool>)item["available"])())
					.Append(((Func<bool>)item["canEdit"])())
					.Append(((Func<int>)item["version"])())
					.Append('|');
			}
			return stringBuilder.ToString();
		}

		private static bool Build()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00c8: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			if (GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				return false;
			}
			GUIManager instance = GUIManager.Instance;
			panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-230f, 0f), 380f, 600f, false);
			((Object)panel).name = "GC_PortalNames";
			((Graphic)GcUi.CreateLabel(panel.transform, GcLoc.Get("gcpn_title", Array.Empty<object>()), new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(20f, -62f), new Vector2(-20f, -18f), 26, (TextAnchor)4, (Color?)instance.ValheimOrange, true)).raycastTarget = false;
			GameObject val = new GameObject("Inner", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(panel.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = new Vector2(18f, 22f);
			val2.offsetMax = new Vector2(-18f, -66f);
			content = GcUi.CreateScroll((Transform)val2, 330f, 500f);
			panel.SetActive(false);
			return true;
		}

		private static void Fill()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			GcUi.ClearChildren((Transform)(object)content);
			bool has;
			string previous = Previous(out has);
			if (has)
			{
				Label(GcLoc.Get("gcpn_previous", Array.Empty<object>()), 21, new Color(1f, 0.75f, 0.4f), 32f);
				((Component)GcUi.CreateButton((Transform)(object)GcUi.CreateRow((Transform)(object)content, 36f), "« " + previous, new Vector2(0f, 0.5f), new Vector2(145f, 0f), 286f, 32f, (Action)delegate
				{
					Apply(previous);
				})).GetComponentInChildren<Text>(true).alignment = (TextAnchor)4;
			}
			foreach (Dictionary<string, object> item in Providers())
			{
				if (!((Func<bool>)item["available"])())
				{
					continue;
				}
				bool flag = ((Func<bool>)item["canEdit"])();
				List<string> obj = ((Func<List<string>>)item["names"])() ?? new List<string>();
				Label(((Func<string>)item["title"])() + (flag ? "" : (" " + GcLoc.Get("gcpn_readonly", Array.Empty<object>()))), 21, new Color(1f, 0.75f, 0.4f), 32f);
				if (obj.Count == 0)
				{
					Label(GcLoc.Get("gcpn_none", Array.Empty<object>()), 15, new Color(0.78f, 0.72f, 0.62f), 26f);
				}
				foreach (string item2 in obj)
				{
					EntryRow(item, item2, flag);
				}
				if (!flag)
				{
					continue;
				}
				Action<string> add = (Action<string>)item["add"];
				ButtonRow(GcLoc.Get("gcpn_add", Array.Empty<object>()), delegate
				{
					TextInput instance = TextInput.instance;
					if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_inputField != (Object)null)
					{
						add(GcPortalNames.Clean(((TMP_InputField)instance.m_inputField).text));
					}
					Refocus();
				});
			}
		}

		private static string Previous(out bool has)
		{
			has = false;
			TextInput instance = TextInput.instance;
			if (GcHooks.IsPortalGuardActive() && !((Object)(object)instance == (Object)null))
			{
				TextReceiver queuedSign = instance.m_queuedSign;
				TeleportWorld val = (TeleportWorld)(object)((queuedSign is TeleportWorld) ? queuedSign : null);
				if (val != null && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid())
				{
					ZDO zDO = val.m_nview.GetZDO();
					string text = zDO.GetString("gc_portal_prev", "") ?? "";
					has = text.Length > 0 && text != (zDO.GetString(ZDOVars.s_tag, "") ?? "");
					return text;
				}
			}
			return "";
		}

		private static void Label(string text, int size, Color color, float height)
		{
			//IL_000c: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)GcUi.CreateLabel((Transform)(object)GcUi.CreateRow((Transform)(object)content, height), text, Vector2.zero, Vector2.one, new Vector2(4f, 0f), Vector2.zero, size, (TextAnchor)6, (Color?)color, false)).raycastTarget = false;
		}

		private static void EntryRow(Dictionary<string, object> provider, string name, bool canEdit)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = GcUi.CreateRow((Transform)(object)content, 36f);
			string text = ((name.Length == 0) ? GcLoc.Get("gcpn_empty", Array.Empty<object>()) : name);
			((Component)GcUi.CreateButton((Transform)(object)val, text, new Vector2(0f, 0.5f), new Vector2(122f, 0f), 240f, 32f, (Action)delegate
			{
				Apply(name);
			})).GetComponentInChildren<Text>(true).alignment = (TextAnchor)4;
			if (canEdit)
			{
				Action<string> remove = (Action<string>)provider["remove"];
				GcUi.CreateButton((Transform)(object)val, "×", new Vector2(1f, 0.5f), new Vector2(-24f, 0f), 36f, 32f, (Action)delegate
				{
					remove(name);
					Refocus();
				});
			}
		}

		private static void ButtonRow(string text, Action onClick)
		{
			//IL_001a: 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)
			GcUi.CreateButton((Transform)(object)GcUi.CreateRow((Transform)(object)content, 40f), text, new Vector2(0.5f, 0.5f), Vector2.zero, 290f, 34f, onClick);
		}

		private static void Refocus()
		{
			TextInput instance = TextInput.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_inputField == (Object)null))
			{
				EventSystem current = EventSystem.current;
				if (current != null)
				{
					current.SetSelectedGameObject(((Component)instance.m_inputField).gameObject);
				}
				instance.m_inputField.ActivateInputField();
			}
		}

		private static void Apply(string name)
		{
			TextInput instance = TextInput.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			TextReceiver queuedSign = instance.m_queuedSign;
			TeleportWorld val = (TeleportWorld)(object)((queuedSign is TeleportWorld) ? queuedSign : null);
			if (val == null)
			{
				return;
			}
			if (!Plugin.ClickRenames.Value)
			{
				((TMP_InputField)instance.m_inputField).text = name;
				Refocus();
				return;
			}
			instance.m_queuedSign = null;
			instance.Hide();
			if (!((val.GetText() ?? "") == name))
			{
				if (GcHooks.IsPortalGuardActive() && GcHooks.PortalRename != null)
				{
					GcHooks.PortalRename(val, name);
				}
				else
				{
					val.SetText(name);
				}
				Gc.TopLeft(GcLoc.Get("gcpn_renamed", new object[1] { (name.Length == 0) ? GcLoc.Get("gcpn_empty", Array.Empty<object>()) : name }));
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Spitzhacke.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Pickaxe;
using GC.Shared;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Spitzhacke")]
[assembly: AssemblyTitle("GC_Spitzhacke")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModSpitzhacke
{
	[BepInPlugin("gorduan.gc.spitzhacke", "GC_Spitzhacke", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.spitzhacke");
			GC.Server.Pickaxe.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			Module.TakeOverOldSettings();
			Module.IsOn = () => GC.Server.Pickaxe.Plugin.On;
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("pickaxe", (ConfigEntryBase)(object)GC.Server.Pickaxe.Plugin.Enabled, (Func<bool>)(() => GC.Server.Pickaxe.Plugin.Blocked), "GC_Pickaxe", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("pickaxe_enemy", (ConfigEntryBase)(object)GC.Server.Pickaxe.Plugin.EnemyPercent, 5.0, " %", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("pickaxe_ore", (ConfigEntryBase)(object)GC.Server.Pickaxe.Plugin.OrePercent, 5.0, " %", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}
	}
	internal static class GcMod
	{
		public const string Id = "spitzhacke";

		public const string Guid = "gorduan.gc.spitzhacke";

		public const string Name = "GC_Spitzhacke";

		public const string Version = "1.8.1";

		public const int Stufe = 4;

		public static GcModInfo Info => new GcModInfo
		{
			Id = "spitzhacke",
			Guid = "gorduan.gc.spitzhacke",
			Name = "GC_Spitzhacke",
			Version = "1.8.1",
			Stufe = 4,
			Seite = (GcSeite)2,
			Braucht = Array.Empty<string>(),
			Partner = Array.Empty<string>(),
			Fremd = Array.Empty<string>(),
			AlteConfig = "gorduan.gc_server.cfg",
			Ausgleich = 1f
		};
	}
}
namespace GC.Server.Pickaxe
{
	internal static class Plugin
	{
		public const string Guid = "gorduan.gc_pickaxe";

		public const string ModName = "GC_Pickaxe";

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<string> AnimationSource = null;

		internal static ConfigEntry<int> EnemyPercent = null;

		internal static ConfigEntry<int> OrePercent = null;

		private static readonly Dictionary<string, Attack> OriginalSecondary = new Dictionary<string, Attack>();

		private static string lastReport = "";

		internal static bool Blocked => Chainloader.PluginInfos.ContainsKey("gorduan.gc_pickaxe");

		internal static bool On
		{
			get
			{
				if (Enabled.Value)
				{
					return !Blocked;
				}
				return false;
			}
		}

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "2 - Pickaxe", "Enabled", true, "Streitkolben-Schlag mit der Spitzhacke auf der mittleren Maustaste (wird vom Server vorgegeben, auch im Menü GC Option).", (AcceptableValueBase)null);
			AnimationSource = Gc.BindSynced<string>(Config, "2 - Pickaxe", "AnimationSource", "MaceBronze", "Streitkolben, dessen Hauptangriff (Animation, Schlagkette, Reichweite, Ausdauer) übernommen wird, z. B. MaceBronze, MaceIron, MaceSilver, MaceNeedle.", (AcceptableValueBase)null);
			EnemyPercent = Gc.BindSynced<int>(Config, "2 - Pickaxe", "EnemyDamagePercent", 125, "Schaden des Kampfschlags gegen Gegner in Prozent des Spitzhacken-Schadens.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 300));
			OrePercent = Gc.BindSynced<int>(Config, "2 - Pickaxe", "OreDamagePercent", 75, "Schaden des Kampfschlags gegen Erz und Gestein in Prozent des Spitzhacken-Schadens.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 300));
			Enabled.SettingChanged += delegate
			{
				Apply(ObjectDB.instance);
			};
			AnimationSource.SettingChanged += delegate
			{
				Apply(ObjectDB.instance);
			};
		}

		internal static void Apply(ObjectDB? db)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Invalid comparison between Unknown and I4
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Invalid comparison between Unknown and I4
			if (Blocked || (Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0)
			{
				return;
			}
			GameObject itemPrefab = db.GetItemPrefab(AnimationSource.Value);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			Attack val2 = (((Object)(object)val != (Object)null) ? val.m_itemData.m_shared.m_attack : null);
			int num = 0;
			foreach (GameObject item in db.m_items)
			{
				ItemDrop val3 = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				SharedData shared = val3.m_itemData.m_shared;
				if ((int)shared.m_skillType == 12)
				{
					if (!OriginalSecondary.ContainsKey(((Object)item).name))
					{
						OriginalSecondary[((Object)item).name] = shared.m_secondaryAttack;
					}
					shared.m_secondaryAttack = (Attack)((On && val2 != null) ? ((object)val2.Clone()) : ((object)OriginalSecondary[((Object)item).name]));
					num++;
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
				{
					ItemDrop val4 = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? allItem.m_dropPrefab.GetComponent<ItemDrop>() : null);
					if ((int)allItem.m_shared.m_skillType == 12 && (Object)(object)val4 != (Object)null && allItem.m_shared != val4.m_itemData.m_shared)
					{
						allItem.m_shared.m_secondaryAttack = val4.m_itemData.m_shared.m_secondaryAttack;
					}
				}
			}
			string text = ((!On) ? $"Kampfschlag aus, {num} Spitzhacken wie Vanilla." : ((val2 == null) ? ("Streitkolben '" + AnimationSource.Value + "' nicht gefunden, kein Kampfschlag.") : $"Kampfschlag von {AnimationSource.Value} (Animation {val2.m_attackAnimation}, {Mathf.Max(1, val2.m_attackChainLevels)} Schläge, Ausdauer {val2.m_attackStamina:0.#}) für {num} Spitzhacken."));
			if (text != lastReport)
			{
				lastReport = text;
				if (On && val2 == null)
				{
					Log.LogWarning((object)text);
				}
				else
				{
					Log.LogInfo((object)text);
				}
			}
		}

		internal static bool IsCombatSwing(Attack attack)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			ItemData weapon = attack.m_weapon;
			if (weapon != null && (int)weapon.m_shared.m_skillType == 12)
			{
				Humanoid character = attack.m_character;
				if (character != null)
				{
					return character.m_currentAttackIsSecondary;
				}
			}
			return false;
		}

		internal static bool IsOre(GameObject target)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			if ((Object)(object)target.GetComponent<MineRock>() != (Object)null || (Object)(object)target.GetComponent<MineRock5>() != (Object)null)
			{
				return true;
			}
			Destructible component = target.GetComponent<Destructible>();
			if ((Object)(object)component == (Object)null || (Object)(object)target.GetComponent<WearNTear>() != (Object)null)
			{
				return false;
			}
			DamageModifier pickaxe = component.m_damages.m_pickaxe;
			if ((int)pickaxe != 3)
			{
				return (int)pickaxe != 4;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDBAwakePatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ObjectDB __instance)
		{
			Plugin.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDBCopyPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ObjectDB __instance)
		{
			Plugin.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(Attack), "ModifyDamage")]
	internal static class ModifyDamagePatch
	{
		private static void Postfix(Attack __instance, HitData hitData)
		{
			if (!Plugin.On || hitData == null || (Object)(object)hitData.m_hitCollider == (Object)null || !Plugin.IsCombatSwing(__instance))
			{
				return;
			}
			GameObject val = Projectile.FindHitObject(hitData.m_hitCollider);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)val.GetComponent<Character>() != (Object)null)
			{
				((DamageTypes)(ref hitData.m_damage)).Modify((float)Plugin.EnemyPercent.Value / 100f);
			}
			else if (Plugin.IsOre(val))
			{
				float num = (float)Plugin.OrePercent.Value / 100f;
				if (__instance.m_attackChainLevels > 1 && __instance.m_currentAttackCainLevel == __instance.m_attackChainLevels - 1)
				{
					num *= 0.5f;
				}
				((DamageTypes)(ref hitData.m_damage)).Modify(num);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Tierarten.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Leash;
using GC.Shared;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Tierarten")]
[assembly: AssemblyTitle("GC_Tierarten")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModTierarten
{
	[BepInPlugin("gorduan.gc.tierarten", "GC_Tierarten", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.tierarten");
			Species.Init(((BaseUnityPlugin)this).Config);
			BearSaddles.Init(((BaseUnityPlugin)this).Config);
			Module.TakeOverOldSettings();
			Module.IsOn = () => Plugin.On || Care.Enabled.Value;
			AddLocalization();
			GcHooks.SpeciesMaxLevel = (int prefab) => Species.MaxLevel(prefab);
			GcHooks.SpeciesEffectCap = () => Species.EffectCap.Value;
			GcHooks.SpeciesEnemyForOrder = Species.EnemyForOrder;
			GcHooks.SpeciesTaming = delegate(Character animal)
			{
				Species.Kind kind2 = Species.Of(animal);
				return (kind2 != Species.Unbjorn && (!kind2.Optional || Species.Enabled(kind2))) ? (kind2.Optional ? ((GcTaming)2) : ((GcTaming)0)) : ((GcTaming)1);
			};
			val.PatchAll(typeof(Plugin).Assembly);
			GcMenuGroup val2 = Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("species_cap", (ConfigEntryBase)(object)Species.EffectCap, (Func<bool>)null, "", (Func<string>)null, 10.0, "", (Func<bool>)null, (Func<bool>)null).Main("species_star1", (ConfigEntryBase)(object)Species.StarChance1, (Func<bool>)null, "", (Func<string>)null, 0.1, " %", (Func<bool>)null, (Func<bool>)null)
				.Main("species_star2", (ConfigEntryBase)(object)Species.StarChance2, (Func<bool>)null, "", (Func<string>)null, 0.1, " %", (Func<bool>)null, (Func<bool>)null);
			Species.Kind[] all = Species.All;
			foreach (Species.Kind kind in all)
			{
				string text = kind.Key.ToLowerInvariant();
				if (kind.Tameable != null)
				{
					val2.Main("species_tame_" + text, (ConfigEntryBase)(object)kind.Tameable, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("species_max_" + text, (ConfigEntryBase)(object)kind.MaxLevel, 10.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
				}
				else
				{
					val2.Main("species_max_" + text, (ConfigEntryBase)(object)kind.MaxLevel, (Func<bool>)null, "", (Func<string>)null, 10.0, "", (Func<bool>)null, (Func<bool>)null);
				}
			}
		}

		private static void AddLocalization()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string[] array = new string[5] { "gc_saddle_bjorn", "gc_saddle_bjorn_desc", "gc_saddle_unbjorn", "gc_saddle_unbjorn_desc", "gc_bjorn_cub" };
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				foreach (KeyValuePair<string, string> item in GcLoc.AllLanguages(text))
				{
					string key = item.Key;
					localization.AddTranslation(ref key, ref text, item.Value);
				}
			}
		}

		private void Update()
		{
			if (!Gc.IsHeadless)
			{
				Module.Guard("Tierarten", (Action)Species.Tick);
			}
		}
	}
	internal static class GcMod
	{
		public const string Id = "tierarten";

		public const string Guid = "gorduan.gc.tierarten";

		public const string Name = "GC_Tierarten";

		public const string Version = "1.8.1";

		public const int Stufe = 5;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "tierarten";
				val.Guid = "gorduan.gc.tierarten";
				val.Name = "GC_Tierarten";
				val.Version = "1.8.1";
				val.Stufe = 5;
				val.Seite = (GcSeite)2;
				val.Braucht = new string[1] { "tiere" };
				val.Partner = Array.Empty<string>();
				val.Fremd = Array.Empty<string>();
				val.AlteConfig = "gorduan.gc_server.cfg";
				val.Ausgleich = 5f;
				return val;
			}
		}
	}
}
namespace GC.Server.Leash
{
	internal static class Species
	{
		internal sealed class Kind
		{
			public string Key = "";

			public string[] Prefabs = Array.Empty<string>();

			public int DefaultMax = 150;

			public bool Optional;

			public string[] Foods = Array.Empty<string>();

			public ConfigEntry<int> MaxLevel;

			public ConfigEntry<bool>? Tameable;

			public readonly HashSet<string> FoodNames = new HashSet<string>();

			public List<ItemDrop> VanillaFood = new List<ItemDrop>();

			public List<ItemDrop> AllFood = new List<ItemDrop>();
		}

		private sealed class Graze
		{
			public ItemDrop? Target;

			public float NextSearch;
		}

		internal const string CubPrefab = "GC_Bjorn_Cub";

		internal const string CubName = "$gc_bjorn_cub";

		internal const string BearName = "$enemy_bjorn";

		internal const string UnbjornName = "$enemy_unbjorn";

		internal const string RottenMeat = "RottenMeat";

		internal const float CubScale = 1f / 3f;

		internal const float CubSaturation = -1f / 3f;

		internal const float CubGrowTime = 6000f;

		internal const double TransformSeconds = 1800.0;

		internal const float LootStep = 50f;

		internal static readonly Kind Wolf = new Kind
		{
			Key = "Wolf",
			Prefabs = new string[2] { "Wolf", "Wolf_cub" },
			DefaultMax = 200
		};

		internal static readonly Kind Lox = new Kind
		{
			Key = "Lox",
			Prefabs = new string[2] { "Lox", "Lox_Calf" },
			DefaultMax = 300
		};

		internal static readonly Kind Boar = new Kind
		{
			Key = "Boar",
			Prefabs = new string[2] { "Boar", "Boar_piggy" }
		};

		internal static readonly Kind Hen = new Kind
		{
			Key = "Hen",
			Prefabs = new string[2] { "Hen", "Chicken" }
		};

		internal static readonly Kind Asksvin = new Kind
		{
			Key = "Asksvin",
			Prefabs = new string[2] { "Asksvin", "Asksvin_hatchling" }
		};

		internal static readonly Kind Moose = new Kind
		{
			Key = "Moose",
			Prefabs = new string[2] { "Moose", "Moose_calf" }
		};

		internal static readonly Kind Bear = new Kind
		{
			Key = "Bjorn",
			Prefabs = new string[2] { "Bjorn", "GC_Bjorn_Cub" },
			DefaultMax = 200,
			Optional = true,
			Foods = new string[5] { "Honey", "Raspberry", "Blueberries", "Cloudberry", "RottenMeat" }
		};

		internal static readonly Kind Unbjorn = new Kind
		{
			Key = "Unbjorn",
			Prefabs = new string[1] { "Unbjorn" },
			DefaultMax = 300
		};

		internal static readonly Kind Neck = new Kind
		{
			Key = "Neck",
			Prefabs = new string[1] { "Neck" },
			Optional = true,
			Foods = new string[1] { "FishRaw" }
		};

		internal static readonly Kind Deer = new Kind
		{
			Key = "Deer",
			Prefabs = new string[1] { "Deer" },
			Optional = true,
			Foods = new string[3] { "Raspberry", "Blueberries", "Mushroom" }
		};

		internal static readonly Kind Hare = new Kind
		{
			Key = "Hare",
			Prefabs = new string[1] { "Hare" },
			Optional = true,
			Foods = new string[3] { "Mushroom", "MushroomYellow", "MushroomJotunPuffs" }
		};

		internal static readonly Kind Seal = new Kind
		{
			Key = "Seal",
			Prefabs = new string[1] { "Seal" },
			Optional = true,
			Foods = new string[1] { "FishRaw" }
		};

		internal static readonly Kind Other = new Kind
		{
			Key = "Other"
		};

		internal static readonly Kind[] All = new Kind[13]
		{
			Wolf, Lox, Boar, Hen, Asksvin, Moose, Bear, Unbjorn, Neck, Deer,
			Hare, Seal, Other
		};

		internal static ConfigEntry<float> EffectCap = null;

		internal static ConfigEntry<float> StarChance1 = null;

		internal static ConfigEntry<float> StarChance2 = null;

		private static readonly Dictionary<int, Kind> ByHash = new Dictionary<int, Kind>();

		private static readonly int BearHash = StringExtensionMethods.GetStableHashCode("Bjorn");

		private static readonly int UnbjornHash = StringExtensionMethods.GetStableHashCode("Unbjorn");

		internal static readonly int TransformHash = StringExtensionMethods.GetStableHashCode("gc_unbjorn_at");

		private const string TellRpc = "GC_SpeciesTell";

		private static string rottenMeatName = "$item_rottenmeat";

		private static EffectList? eatEffects;

		private static float nextTick;

		private static bool bypassPeace;

		private static readonly Dictionary<AnimalAI, Graze> Grazing = new Dictionary<AnimalAI, Graze>();

		private static int itemMask;

		internal static void Init(ConfigFile config)
		{
			EffectCap = Gc.BindSynced<float>(config, "14 - Animal Species", "EffectCap", 150f, "Höchste wirksame Stufe für die Boni: halbe eigene Stufe + Tierpflege des Pflegers zusammen (Jan: Grenze A, wie bisher 150). Darüber bringt der Pfleger nichts mehr.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 1000f));
			StarChance1 = Gc.BindSynced<float>(config, "14 - Animal Species", "StarChance1", 1f, "Prozent-Chance, dass ein Junges (oder Ei), das ohne Stern wäre, einen Stern bekommt (Jan: 1 %).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			StarChance2 = Gc.BindSynced<float>(config, "14 - Animal Species", "StarChance2", 0.5f, "Prozent-Chance, dass ein Junges (oder Ei) mit einem Stern zwei bekommt (Jan: 0,5 %).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			Kind[] all = All;
			foreach (Kind kind in all)
			{
				string text = ((kind == Other) ? "alle anderen zahmen Tiere (auch aus anderen Mods)" : string.Join(", ", kind.Prefabs));
				kind.MaxLevel = Gc.BindSynced<int>(config, "14 - Animal Species", "MaxLevel" + kind.Key, kind.DefaultMax, "Höchststufe (Zucht und Erfahrung): " + text + ".", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000));
				if (kind.Optional)
				{
					string text2 = ((kind == Bear) ? " Dazu: Bärenjunge, Verwandlung in einen Unbjørn mit verrottetem Fleisch, Sättel für Bär und Unbjørn." : "");
					kind.Tameable = Gc.BindSynced<bool>(config, "14 - Animal Species", "Tameable" + kind.Key, false, "Jan: " + kind.Prefabs[0] + " lässt sich zähmen (Futter: " + string.Join(", ", kind.Foods) + ") und anleinen." + text2, (AcceptableValueBase)null);
				}
				string[] prefabs = kind.Prefabs;
				foreach (string text3 in prefabs)
				{
					ByHash[StringExtensionMethods.GetStableHashCode(text3)] = kind;
				}
			}
			PrefabManager.OnVanillaPrefabsAvailable += SetupPrefabs;
		}

		internal static Kind Of(int prefabHash)
		{
			if (!ByHash.TryGetValue(prefabHash, out Kind value))
			{
				return Other;
			}
			return value;
		}

		internal static Kind Of(Character? character)
		{
			ZNetView val = (((Object)(object)character != (Object)null) ? character.m_nview : null);
			ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
			if (val2 == null)
			{
				return Other;
			}
			return Of(val2.GetPrefab());
		}

		internal static float MaxLevel(int prefabHash)
		{
			return Mathf.Max(1, Of(prefabHash).MaxLevel.Value);
		}

		internal static float MaxLevel(Character? character)
		{
			return Mathf.Max(1, Of(character).MaxLevel.Value);
		}

		internal static bool Enabled(Kind kind)
		{
			if (kind == Unbjorn)
			{
				if (Bear.Tameable != null)
				{
					return Bear.Tameable.Value;
				}
				return false;
			}
			if (kind.Tameable != null)
			{
				return kind.Tameable.Value;
			}
			return true;
		}

		private static bool IsBear(Character c)
		{
			if (!(c.m_name == "$enemy_bjorn"))
			{
				return c.m_name == "$gc_bjorn_cub";
			}
			return true;
		}

		private static bool IsWild(Character c)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			if (c.IsPlayer() || c.IsTamed())
			{
				return false;
			}
			Faction faction = c.GetFaction();
			if ((int)faction != 0 && (int)faction != 11)
			{
				return (int)faction != 12;
			}
			return false;
		}

		private static void SetupPrefabs()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= SetupPrefabs;
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("Wolf");
				Tameable template = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Tameable>() : null);
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("Lox");
				Humanoid val = ((prefab2 != null) ? prefab2.GetComponent<Humanoid>() : null);
				eatEffects = (((Object)(object)val != (Object)null) ? val.m_consumeItemEffects : null);
				GameObject prefab3 = PrefabManager.Instance.GetPrefab("RottenMeat");
				ItemDrop val2 = ((prefab3 != null) ? prefab3.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					rottenMeatName = val2.m_itemData.m_shared.m_name;
				}
				Kind[] array = new Kind[6] { Bear, Unbjorn, Neck, Deer, Hare, Seal };
				foreach (Kind kind in array)
				{
					string[] foods = kind.Foods;
					foreach (string text in foods)
					{
						GameObject prefab4 = PrefabManager.Instance.GetPrefab(text);
						ItemDrop val3 = ((prefab4 != null) ? prefab4.GetComponent<ItemDrop>() : null);
						if ((Object)(object)val3 == (Object)null)
						{
							ServerPlugin.Log.LogInfo((object)("Tierarten: Futter " + text + " gibt es im Spiel nicht."));
							continue;
						}
						kind.FoodNames.Add(val3.m_itemData.m_shared.m_name);
						kind.AllFood.Add(val3);
					}
					foods = kind.Prefabs;
					foreach (string text2 in foods)
					{
						if (text2 == "GC_Bjorn_Cub")
						{
							continue;
						}
						GameObject prefab5 = PrefabManager.Instance.GetPrefab(text2);
						if ((Object)(object)prefab5 == (Object)null)
						{
							ServerPlugin.Log.LogInfo((object)("Tierarten: " + text2 + " gibt es im Spiel nicht."));
							continue;
						}
						AddTameable(prefab5, template);
						MonsterAI component = prefab5.GetComponent<MonsterAI>();
						if (!((Object)(object)component != (Object)null) || kind.AllFood.Count <= 0)
						{
							continue;
						}
						kind.VanillaFood = new List<ItemDrop>(component.m_consumeItems ?? new List<ItemDrop>());
						List<ItemDrop> list = new List<ItemDrop>(kind.VanillaFood);
						foreach (ItemDrop item in kind.AllFood)
						{
							if (!list.Contains(item))
							{
								list.Add(item);
							}
						}
						kind.AllFood = list;
					}
				}
				GameObject prefab6 = PrefabManager.Instance.GetPrefab("Bjorn");
				if ((Object)(object)prefab6 != (Object)null)
				{
					CreateCub(prefab6);
					AddProcreation(prefab6);
				}
				ServerPlugin.Log.LogInfo((object)"Tierarten: Nixe, Hirsch, Hase, Robbe und Bär vorbereitet (zähmbar nur, wenn im Menü an), Bärenjunges angelegt.");
			}
			catch (Exception arg)
			{
				ServerPlugin.Log.LogWarning((object)$"Tierarten: Vorbereitung fehlgeschlagen: {arg}");
			}
		}

		private static void AddTameable(GameObject prefab, Tameable? template)
		{
			Tameable val = prefab.GetComponent<Tameable>() ?? prefab.AddComponent<Tameable>();
			val.m_fedDuration = 600f;
			val.m_tamingTime = 1800f;
			val.m_commandable = false;
			if ((Object)(object)template != (Object)null)
			{
				val.m_tamedEffect = template.m_tamedEffect;
				val.m_sootheEffect = template.m_sootheEffect;
				val.m_petEffect = template.m_petEffect;
				val.m_tamingSpeedMultiplierRange = template.m_tamingSpeedMultiplierRange;
				val.m_tamingBoostMultiplier = template.m_tamingBoostMultiplier;
			}
		}

		private static void CreateCub(GameObject bear)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("GC_Bjorn_Cub", "Bjorn");
			if ((Object)(object)val == (Object)null)
			{
				ServerPlugin.Log.LogWarning((object)"Tierarten: Bärenjunges nicht angelegt, Bären bekommen keine Jungen.");
				return;
			}
			Type[] array = new Type[3]
			{
				typeof(Procreation),
				typeof(CharacterDrop),
				typeof(Growup)
			};
			foreach (Type type in array)
			{
				Component[] components = val.GetComponents(type);
				for (int j = 0; j < components.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)components[j]);
				}
			}
			val.transform.localScale = bear.transform.localScale * (1f / 3f);
			Character component = val.GetComponent<Character>();
			Character component2 = bear.GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "$gc_bjorn_cub";
				component.m_health = (((Object)(object)component2 != (Object)null) ? component2.m_health : component.m_health) * (1f / 3f);
			}
			Growup obj = val.AddComponent<Growup>();
			obj.m_growTime = 6000f;
			obj.m_grownPrefab = bear;
			obj.m_inheritTame = true;
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				Material[] sharedMaterials = val2.sharedMaterials;
				bool flag = false;
				for (int k = 0; k < sharedMaterials.Length; k++)
				{
					if ((Object)(object)sharedMaterials[k] != (Object)null && sharedMaterials[k].HasProperty("_Saturation"))
					{
						Material val3 = new Material(sharedMaterials[k])
						{
							name = ((Object)sharedMaterials[k]).name + "_gc_cub"
						};
						val3.SetFloat("_Saturation", val3.GetFloat("_Saturation") + -1f / 3f);
						sharedMaterials[k] = val3;
						flag = true;
					}
				}
				if (flag)
				{
					val2.sharedMaterials = sharedMaterials;
				}
			}
			PrefabManager.Instance.AddPrefab(new CustomPrefab(val, true));
		}

		private static void AddProcreation(GameObject bear)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("GC_Bjorn_Cub");
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("Lox");
			Procreation val = ((prefab2 != null) ? prefab2.GetComponent<Procreation>() : null);
			if (!((Object)(object)prefab == (Object)null) && !((Object)(object)bear.GetComponent<Procreation>() != (Object)null))
			{
				Procreation val2 = bear.AddComponent<Procreation>();
				val2.m_offspring = prefab;
				val2.m_updateInterval = 30f;
				val2.m_pregnancyChance = 0.33f;
				val2.m_pregnancyDuration = 120f;
				val2.m_requiredLovePoints = 4;
				val2.m_maxCreatures = 4;
				val2.m_totalCheckRange = 20f;
				val2.m_partnerCheckRange = 8f;
				val2.m_spawnOffset = 2f;
				if ((Object)(object)val != (Object)null)
				{
					val2.m_birthEffects = val.m_birthEffects;
					val2.m_loveEffects = val.m_loveEffects;
				}
			}
		}

		internal static void Mutate(Spawning? birth)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (birth == null || !birth.Done)
			{
				return;
			}
			if ((Object)(object)birth.Born != (Object)null && (Object)(object)birth.Born.m_nview != (Object)null && birth.Born.m_nview.IsValid() && birth.Born.m_nview.IsOwner())
			{
				Character born = birth.Born;
				int level = born.GetLevel();
				int num = Roll(level);
				if (num > level)
				{
					born.SetLevel(num);
					born.SetHealth(born.GetMaxHealth());
					Tell(birth.Breeder, ((Component)born).transform.position, (num == 2) ? "gcs_star_born1" : "gcs_star_born2", born.GetHoverName());
				}
				return;
			}
			ItemDrop egg = birth.Egg;
			if ((Object)(object)egg != (Object)null && (Object)(object)egg.m_nview != (Object)null && egg.m_nview.IsValid() && egg.m_nview.IsOwner())
			{
				int quality = egg.m_itemData.m_quality;
				int num2 = Roll(quality);
				if (num2 > quality)
				{
					egg.SetQuality(num2);
					egg.Save();
					Tell(birth.Breeder, ((Component)egg).transform.position, (num2 == 2) ? "gcs_star_egg1" : "gcs_star_egg2", Localization.instance.Localize(egg.m_itemData.m_shared.m_name));
				}
			}
		}

		private static int Roll(int level)
		{
			float num = Random.value * 100f;
			if (level == 1 && num < StarChance1.Value)
			{
				return 2;
			}
			if (level == 2 && num < StarChance2.Value)
			{
				return 3;
			}
			return level;
		}

		internal static void RegisterRpcs()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.Register<string, string>("GC_SpeciesTell", (Action<long, string, string>)RPC_Tell);
			}
		}

		private static void Tell(long session, Vector3 position, string key, string name)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (session == 0L)
			{
				Player closestPlayer = Player.GetClosestPlayer(position, 30f);
				if ((Object)(object)closestPlayer == (Object)null)
				{
					return;
				}
				session = Links.Session(closestPlayer);
			}
			if ((Object)(object)localPlayer != (Object)null && Links.Session(localPlayer) == session)
			{
				((Character)localPlayer).Message((MessageType)2, GcLoc.Get(key, new object[1] { name }), 0, (Sprite)null, false);
				return;
			}
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC(session, "GC_SpeciesTell", new object[2] { key, name });
			}
		}

		private static void RPC_Tell(long sender, string key, string name)
		{
			if (key.StartsWith("gcs_", StringComparison.Ordinal))
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, GcLoc.Get(key, new object[1] { name }), 0, (Sprite)null, false);
				}
			}
		}

		internal static void GrazeUpdate(AnimalAI ai, float dt)
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Character character = ((BaseAI)ai).m_character;
			if ((Object)(object)character == (Object)null || character.IsTamed())
			{
				return;
			}
			Kind kind = Of(character);
			if (!kind.Optional || !Enabled(kind) || kind.FoodNames.Count == 0 || ((BaseAI)ai).IsAlerted())
			{
				return;
			}
			Tameable component = ((Component)character).GetComponent<Tameable>();
			if ((Object)(object)component == (Object)null || !component.IsHungry())
			{
				return;
			}
			if (!Grazing.TryGetValue(ai, out Graze value))
			{
				value = (Grazing[ai] = new Graze());
			}
			float time = Time.time;
			if ((Object)(object)value.Target == (Object)null && time >= value.NextSearch)
			{
				value.NextSearch = time + 2f;
				value.Target = FindFood(ai, kind);
			}
			ItemDrop target = value.Target;
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			if ((Object)(object)target.m_nview == (Object)null || !target.m_nview.IsValid())
			{
				value.Target = null;
			}
			else
			{
				if (!((BaseAI)ai).MoveTo(dt, ((Component)target).transform.position, 1.2f, false))
				{
					return;
				}
				((BaseAI)ai).LookAt(((Component)target).transform.position);
				if (target.RemoveOne())
				{
					component.OnConsumedItem(target);
					EffectList? obj = eatEffects;
					if (obj != null)
					{
						obj.Create(((Component)character).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
					}
				}
				value.Target = null;
			}
		}

		private static ItemDrop? FindFood(AnimalAI ai, Kind kind)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			if (itemMask == 0)
			{
				itemMask = LayerMask.GetMask(new string[1] { "item" });
			}
			ItemDrop val = null;
			float num = float.MaxValue;
			Collider[] array = Physics.OverlapSphere(((Component)ai).transform.position, 10f, itemMask);
			foreach (Collider val2 in array)
			{
				ItemDrop val3 = (((Object)(object)val2.attachedRigidbody != (Object)null) ? ((Component)val2.attachedRigidbody).GetComponent<ItemDrop>() : null);
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.m_nview == (Object)null) && val3.m_nview.IsValid() && kind.FoodNames.Contains(val3.m_itemData.m_shared.m_name))
				{
					float num2 = Vector3.Distance(((Component)val3).transform.position, ((Component)ai).transform.position);
					if (num2 < num)
					{
						val = val3;
						num = num2;
					}
				}
			}
			if (!((Object)(object)val != (Object)null) || !((BaseAI)ai).HavePath(((Component)val).transform.position))
			{
				return null;
			}
			return val;
		}

		internal static void AnimalTamingUpdate(Tameable tame, Character character)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = tame.m_nview;
			BaseAI baseAI = character.GetBaseAI();
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner() || tame.IsHungry() || (Object)(object)baseAI == (Object)null || baseAI.IsAlerted())
			{
				return;
			}
			tame.DecreaseRemainingTime(3f);
			if (tame.GetRemainingTime() > 0f)
			{
				tame.m_sootheEffect.Create(((Component)character).transform.position, ((Component)character).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				return;
			}
			character.SetTamed(true);
			tame.m_tamedEffect.Create(((Component)character).transform.position, ((Component)character).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			Game.instance.IncrementPlayerStat((PlayerStatType)48, 1f, false);
			Player closestPlayer = Player.GetClosestPlayer(((Component)character).transform.position, 30f);
			if (closestPlayer != null)
			{
				((Character)closestPlayer).Message((MessageType)2, character.m_name + " $hud_tamedone", 0, (Sprite)null, false);
			}
			Care.Grant(Care.CaretakerOf(character, nview.GetZDO(), 30f), Care.TameXp.Value);
		}

		internal static void OnBearAte(Tameable tame, ItemDrop? item)
		{
			Character character = tame.m_character;
			ZNetView nview = tame.m_nview;
			if (!((Object)(object)item == (Object)null) && !((Object)(object)character == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && Enabled(Bear) && !((Object)(object)ZNet.instance == (Object)null) && nview.GetZDO().GetPrefab() == BearHash && !(item.m_itemData.m_shared.m_name != rottenMeatName))
			{
				ZDO zDO = nview.GetZDO();
				if (zDO.GetLong(TransformHash, 0L) == 0L)
				{
					zDO.Set(TransformHash, ZNet.instance.GetTime().AddSeconds(1800.0).Ticks);
				}
			}
		}

		internal static void Tick()
		{
			float time = Time.time;
			if (time < nextTick || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			nextTick = time + 5f;
			if (Grazing.Count > 0)
			{
				List<AnimalAI> list = new List<AnimalAI>();
				foreach (KeyValuePair<AnimalAI, Graze> item in Grazing)
				{
					if ((Object)(object)item.Key == (Object)null)
					{
						list.Add(item.Key);
					}
				}
				foreach (AnimalAI item2 in list)
				{
					Grazing.Remove(item2);
				}
			}
			if (!Enabled(Bear))
			{
				return;
			}
			long ticks = ZNet.instance.GetTime().Ticks;
			foreach (Character item3 in new List<Character>(Character.GetAllCharacters()))
			{
				ZNetView val = (((Object)(object)item3 != (Object)null) ? item3.m_nview : null);
				if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner() || item3.IsDead())
				{
					continue;
				}
				ZDO zDO = val.GetZDO();
				if (zDO.GetPrefab() == BearHash)
				{
					long num = zDO.GetLong(TransformHash, 0L);
					if (num != 0L && ticks >= num)
					{
						Transform(item3);
					}
				}
			}
		}

		private static void Transform(Character bear)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab("Unbjorn");
			ZDO zDO = bear.m_nview.GetZDO();
			zDO.Set(TransformHash, 0L);
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)bear).transform.position;
			Character component = Object.Instantiate<GameObject>(prefab, position, ((Component)bear).transform.rotation).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid())
			{
				return;
			}
			bool flag = bear.IsTamed();
			component.SetLevel(bear.GetLevel());
			if (flag)
			{
				component.SetTamed(true);
			}
			ZDO zDO2 = component.m_nview.GetZDO();
			zDO2.Set(Care.LevelHash, zDO.GetFloat(Care.LevelHash, 0f));
			zDO2.Set(AnimalExperience.XpHash, zDO.GetFloat(AnimalExperience.XpHash, 0f));
			Young.CopyState(bear, component);
			Young.Relink(bear, component, "gcls_transformed");
			if (zDO.GetBool(ZDOVars.s_haveSaddleHash, false))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab("GC_SaddleBjorn");
				if ((Object)(object)prefab2 != (Object)null)
				{
					string text = zDO.GetString(Saddles.DataHash, "");
					Saddles.Dropping = ((text.Length > 0) ? text : null);
					try
					{
						Object.Instantiate<GameObject>(prefab2, position + Vector3.up * 1.5f, Quaternion.identity);
					}
					finally
					{
						Saddles.Dropping = null;
					}
				}
			}
			string[] array = new string[2] { "fx_unbjorn_hit", "vfx_spawn_large" };
			foreach (string text2 in array)
			{
				GameObject prefab3 = ZNetScene.instance.GetPrefab(text2);
				if ((Object)(object)prefab3 != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab3, position, Quaternion.identity);
				}
			}
			string hoverName = bear.GetHoverName();
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null && Vector3.Distance(((Component)allPlayer).transform.position, position) < 40f)
				{
					Tell(Links.Session(allPlayer), position, "gcs_unbjorn", hoverName);
				}
			}
			ZNetScene.instance.Destroy(((Component)bear).gameObject);
			ServerPlugin.Log.LogInfo((object)$"Tierarten: {hoverName} hat sich in einen Unbjørn verwandelt (zahm: {flag}).");
		}

		internal static bool EnemyForOrder(Character animal, Character target)
		{
			bypassPeace = true;
			try
			{
				return BaseAI.IsEnemy(animal, target);
			}
			finally
			{
				bypassPeace = false;
			}
		}

		internal static void EnemyRules(Character a, Character b, ref bool result)
		{
			if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null || (Object)(object)a == (Object)(object)b)
			{
				return;
			}
			if (a.m_name == "$enemy_unbjorn" && a.IsTamed())
			{
				if (IsWild(b))
				{
					result = true;
				}
			}
			else if (b.m_name == "$enemy_unbjorn" && b.IsTamed())
			{
				if (IsWild(a))
				{
					result = true;
				}
			}
			else if (result && !bypassPeace && IsBear(a) && IsBear(b) && a.IsTamed() != b.IsTamed())
			{
				Character obj = (a.IsTamed() ? a : b);
				Character val = (a.IsTamed() ? b : a);
				Link val2 = Links.ForAnimal(obj);
				if (val2 == null || (Object)(object)val2.AttackTarget != (Object)(object)val)
				{
					result = false;
				}
			}
		}

		internal static void LevelLoot(CharacterDrop drop, List<KeyValuePair<GameObject, int>> loot)
		{
			Character character = drop.m_character;
			ZNetView val = (((Object)(object)character != (Object)null) ? character.m_nview : null);
			if (loot == null || loot.Count == 0 || (Object)(object)val == (Object)null || !val.IsValid())
			{
				return;
			}
			float num = val.GetZDO().GetFloat(Care.LevelHash, 0f);
			if (num <= 0f || Random.value >= 0.5f)
			{
				return;
			}
			float num2 = 1f + num / 50f;
			float num3 = Random.Range(Mathf.Min(2f, num2), num2);
			for (int i = 0; i < loot.Count; i++)
			{
				float num4 = (float)loot[i].Value * num3;
				int num5 = Mathf.FloorToInt(num4);
				if (Random.value < num4 - (float)num5)
				{
					num5++;
				}
				loot[i] = new KeyValuePair<GameObject, int>(loot[i].Key, Mathf.Max(loot[i].Value, num5));
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")]
	internal static class SpeciesConsumePatch
	{
		private static void Prefix(MonsterAI __instance)
		{
			Character character = ((BaseAI)__instance).m_character;
			Species.Kind kind = Species.Of(character);
			if (kind.Optional && kind.AllFood.Count != 0)
			{
				List<ItemDrop> list = ((Species.Enabled(kind) || ((Object)(object)character != (Object)null && character.IsTamed())) ? kind.AllFood : kind.VanillaFood);
				if (__instance.m_consumeItems != list)
				{
					__instance.m_consumeItems = list;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "TamingUpdate")]
	internal static class SpeciesTamingPatch
	{
		private static bool Prefix(Tameable __instance)
		{
			Character character = __instance.m_character;
			if ((Object)(object)character == (Object)null || character.IsTamed())
			{
				return true;
			}
			Species.Kind kind = Species.Of(character);
			if (kind == Species.Unbjorn)
			{
				return false;
			}
			if (!kind.Optional)
			{
				return true;
			}
			if (!Species.Enabled(kind))
			{
				return false;
			}
			if ((Object)(object)__instance.m_monsterAI != (Object)null)
			{
				return true;
			}
			Species.AnimalTamingUpdate(__instance, character);
			return false;
		}
	}
	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	internal static class SpeciesHoverPatch
	{
		private static void Postfix(Tameable __instance, ref string __result)
		{
			Character character = __instance.m_character;
			if (!((Object)(object)character == (Object)null) && !character.IsTamed())
			{
				Species.Kind kind = Species.Of(character);
				if (kind == Species.Unbjorn || (kind.Optional && !Species.Enabled(kind)))
				{
					__result = "";
				}
			}
		}
	}
	[HarmonyPatch(typeof(AnimalAI), "UpdateAI")]
	internal static class SpeciesGrazePatch
	{
		private static void Postfix(AnimalAI __instance, float dt, bool __result)
		{
			if (__result)
			{
				Species.GrazeUpdate(__instance, dt);
			}
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class SpeciesProcreatePatch
	{
		private static bool Prefix(Procreation __instance)
		{
			Character character = __instance.m_character;
			if (!((Object)(object)character == (Object)null) && Species.Of(character) == Species.Bear)
			{
				return Species.Enabled(Species.Bear);
			}
			return true;
		}

		private static void Postfix()
		{
			Species.Mutate(Care.Birth);
		}
	}
	[HarmonyPatch(typeof(Tameable), "OnConsumedItem")]
	internal static class SpeciesBearAtePatch
	{
		private static void Postfix(Tameable __instance, ItemDrop item)
		{
			Species.OnBearAte(__instance, item);
		}
	}
	[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
	{
		typeof(Character),
		typeof(Character)
	})]
	internal static class SpeciesEnemyPatch
	{
		private static void Postfix(Character a, Character b, ref bool __result)
		{
			Species.EnemyRules(a, b, ref __result);
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class SpeciesCubDamagePatch
	{
		private static void Prefix(HitData hit)
		{
			Character val = ((hit != null) ? hit.GetAttacker() : null);
			if ((Object)(object)val != (Object)null && val.m_name == "$gc_bjorn_cub")
			{
				hit.ApplyModifier(1f / 3f);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "OnRagdollCreated")]
	internal static class SpeciesCubRagdollPatch
	{
		private static void Postfix(Humanoid __instance, Ragdoll ragdoll)
		{
			//IL_0024: 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_0048: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ragdoll == (Object)null) && !(((Character)__instance).m_name != "$gc_bjorn_cub"))
			{
				Transform transform = ((Component)ragdoll).transform;
				if (transform.localScale.x > ((Component)__instance).transform.localScale.x * 1.1f)
				{
					transform.localScale *= 1f / 3f;
				}
				ZNetView component = ((Component)ragdoll).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					component.GetZDO().Set(GcKeys.RagdollScaleHash, transform.localScale.x);
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	internal static class SpeciesLootPatch
	{
		private static void Postfix(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result)
		{
			Species.LevelLoot(__instance, __result);
		}
	}
	internal static class BearSaddles
	{
		private sealed class Fit
		{
			public string Creature = "";

			public string Item = "";

			public string Name = "";

			public string Bone = "Spine_02";

			public Vector3 Origin;

			public Vector3 Attach;

			public float Scale = 1f;

			public float Radius = 0.35f;

			public string Animation = "attach_asksvin";

			public Color Leather;

			public Color Strap;

			public Color Metal;

			public Color Cloth;

			public (string Item, int Amount)[] Recipe = Array.Empty<(string, int)>();

			public CustomItem? Custom;
		}

		private static readonly Fit[] Fits = new Fit[2]
		{
			new Fit
			{
				Creature = "Bjorn",
				Item = "GC_SaddleBjorn",
				Name = "gc_saddle_bjorn",
				Origin = new Vector3(0f, 2.26f, -0.55f),
				Attach = new Vector3(0f, 2.46f, -0.62f),
				Scale = 1f,
				Radius = 0.35f,
				Animation = "attach_asksvin",
				Leather = new Color(0.45f, 0.28f, 0.15f),
				Strap = new Color(0.22f, 0.13f, 0.07f),
				Metal = new Color(0.72f, 0.5f, 0.24f),
				Cloth = new Color(0.5f, 0.13f, 0.1f),
				Recipe = new(string, int)[2]
				{
					("BjornHide", 5),
					("Bronze", 10)
				}
			},
			new Fit
			{
				Creature = "Unbjorn",
				Item = "GC_SaddleUnbjorn",
				Name = "gc_saddle_unbjorn",
				Origin = new Vector3(0f, 2.9f, -0.72f),
				Attach = new Vector3(0f, 3.16f, -0.8f),
				Scale = 1.3f,
				Radius = 0.45f,
				Animation = "attach_lox",
				Leather = new Color(0.2f, 0.17f, 0.15f),
				Strap = new Color(0.08f, 0.07f, 0.06f),
				Metal = new Color(0.36f, 0.38f, 0.42f),
				Cloth = new Color(0.62f, 0.6f, 0.55f),
				Recipe = new(string, int)[3]
				{
					("UndeadBjornRibcage", 5),
					("BjornHide", 5),
					("BlackMetal", 20)
				}
			}
		};

		private static Mesh? model;

		private static bool modelLoaded;

		internal static void Init(ConfigFile config)
		{
			PrefabManager.OnVanillaPrefabsAvailable += Setup;
		}

		internal static Mesh? Model()
		{
			if (!modelLoaded)
			{
				modelLoaded = true;
				Gcm obj = Gcm.Read("baerensattel.gcm");
				model = ((obj != null) ? obj.ToMesh("GC_Baerensattel") : null);
			}
			return model;
		}

		private static void Setup()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Setup;
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("Lox");
				Sadle template = ((prefab != null) ? prefab.GetComponentInChildren<Sadle>(true) : null);
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("SaddleLox");
				ItemDrop val = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
				Material baseMaterial = null;
				if ((Object)(object)val != (Object)null)
				{
					Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val2 in componentsInChildren)
					{
						bool flag = ((val2 is MeshRenderer || val2 is SkinnedMeshRenderer) ? true : false);
						if (flag && (Object)(object)val2.sharedMaterial != (Object)null)
						{
							baseMaterial = val2.sharedMaterial;
							break;
						}
					}
				}
				int num = 0;
				Fit[] fits = Fits;
				foreach (Fit fit in fits)
				{
					Material material = ((Gc.IsHeadless || (Object)(object)Model() == (Object)null) ? null : MaterialFor(fit, baseMaterial));
					if (CreateItem(fit, material) && AddToCreature(fit, template, material))
					{
						num++;
					}
				}
				ApplyRecipes();
				Species.Bear.Tameable.SettingChanged += delegate
				{
					ApplyRecipes();
				};
				ServerPlugin.Log.LogInfo((object)string.Format("Sättel: {0} Sättel für Bär und Unbjørn angelegt (Modell {1}), Lox- und Asksvin-Sattel als EpicLoot-Items.", num, ((Object)(object)Model() != (Object)null) ? "geladen" : "fehlt"));
			}
			catch (Exception arg)
			{
				ServerPlugin.Log.LogWarning((object)$"Sättel: nicht angelegt: {arg}");
			}
		}

		internal static void ApplyRecipes()
		{
			Fit[] fits = Fits;
			foreach (Fit fit in fits)
			{
				CustomItem? custom = fit.Custom;
				object obj;
				if (custom == null)
				{
					obj = null;
				}
				else
				{
					CustomRecipe recipe = custom.Recipe;
					obj = ((recipe != null) ? recipe.Recipe : null);
				}
				if ((Object)obj != (Object)null)
				{
					fit.Custom.Recipe.Recipe.m_enabled = Species.Enabled(Species.Bear);
				}
			}
		}

		private static bool CreateItem(Fit fit, Material? material)
		{
			//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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			List<RequirementConfig> list = new List<RequirementConfig>();
			(string, int)[] recipe = fit.Recipe;
			for (int i = 0; i < recipe.Length; i++)
			{
				var (text, num) = recipe[i];
				if ((Object)(object)PrefabManager.Instance.GetPrefab(text) == (Object)null)
				{
					ServerPlugin.Log.LogInfo((object)("Sättel: Zutat " + text + " gibt es im Spiel nicht, " + fit.Item + " entfällt."));
					return false;
				}
				list.Add(new RequirementConfig(text, num, 0, true));
			}
			string text2 = "$" + fit.Name;
			ItemConfig val = new ItemConfig
			{
				Name = text2,
				Description = text2 + "_desc",
				CraftingStation = CraftingStations.Forge,
				MinStationLevel = 1,
				Requirements = list.ToArray()
			};
			CustomItem val2 = new CustomItem(fit.Item, "SaddleLox", val);
			SharedData shared = val2.ItemDrop.m_itemData.m_shared;
			shared.m_name = text2;
			shared.m_description = text2 + "_desc";
			shared.m_maxStackSize = 1;
			Dress(((Component)val2.ItemDrop).gameObject, material);
			Sprite val3 = Icon(((Component)val2.ItemDrop).gameObject);
			if ((Object)(object)val3 != (Object)null)
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 };
			}
			if (!ItemManager.Instance.AddItem(val2))
			{
				ServerPlugin.Log.LogWarning((object)("Sättel: " + fit.Item + " konnte nicht registriert werden."));
				return false;
			}
			fit.Custom = val2;
			Saddles.AddName(text2);
			return true;
		}

		private static void Dress(GameObject prefab, Material? material)
		{
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).gameObject == (Object)(object)prefab)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				else if (!list.Contains(((Component)val).gameObject))
				{
					list.Add(((Component)val).gameObject);
				}
			}
			foreach (GameObject item in list)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)item);
				}
			}
			MeshFilter[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			LODGroup[] componentsInChildren3 = prefab.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Collider[] componentsInChildren4 = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			Mesh val2 = Model();
			Bounds val3 = (Bounds)(((Object)(object)val2 != (Object)null) ? val2.bounds : new Bounds(new Vector3(0f, 0f, 0f), new Vector3(1.2f, 0.5f, 1f)));
			BoxCollider obj = prefab.AddComponent<BoxCollider>();
			obj.center = ((Bounds)(ref val3)).center;
			obj.size = ((Bounds)(ref val3)).size;
			if ((Object)(object)val2 != (Object)null && (Object)(object)material != (Object)null)
			{
				prefab.AddComponent<MeshFilter>().sharedMesh = val2;
				((Renderer)prefab.AddComponent<MeshRenderer>()).sharedMaterial = material;
			}
		}

		private static Sprite? Icon(GameObject prefab)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			if (Gc.IsHeadless || (Object)(object)Model() == (Object)null)
			{
				return null;
			}
			try
			{
				Quaternion rotation = Quaternion.AngleAxis(-25f, Vector3.right) * Quaternion.AngleAxis(-40f, Vector3.up);
				return RenderManager.Instance.Render(new RenderRequest(prefab)
				{
					Width = 128,
					Height = 128,
					Rotation = rotation
				});
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Sättel: Symbol nicht gerendert: " + ex.Message));
				return null;
			}
		}

		private static Material MaterialFor(Fit fit, Material? baseMaterial)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Material val = (((Object)(object)baseMaterial != (Object)null) ? new Material(baseMaterial) : new Material(Shader.Find("Standard") ?? Shader.Find("Diffuse")));
			((Object)val).name = fit.Item + "_mat";
			val.mainTexture = (Texture)(object)Atlas(fit);
			if (val.HasProperty("_BumpMap"))
			{
				val.SetTexture("_BumpMap", (Texture)null);
			}
			return val;
		}

		private static Texture2D Atlas(Fit fit)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_009b: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = fit.Item + "_tex",
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			Random random = new Random(StringExtensionMethods.GetStableHashCode(fit.Item));
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j + 0.5f) / 64f;
					float num2 = ((float)i + 0.5f) / 64f;
					float num3 = (float)random.NextDouble() * 0.08f - 0.04f;
					Color val2;
					if (num < 0.5f)
					{
						val2 = fit.Leather * (1f + num3);
						if (j % 32 == 1 || i % 16 == 1)
						{
							val2 *= 0.75f;
						}
					}
					else if (num < 0.75f)
					{
						val2 = fit.Strap * (1f + num3);
						if (j == 33 || j == 46)
						{
							val2 = Color.Lerp(val2, fit.Leather, 0.5f);
						}
					}
					else if (num2 < 0.5f)
					{
						val2 = fit.Metal * (1f + num3 * 1.5f);
						if ((j + i) % 7 == 0)
						{
							val2 *= 1.25f;
						}
					}
					else
					{
						val2 = fit.Cloth * (1f + num3);
						if (i / 4 % 3 == 0)
						{
							val2 = Color.Lerp(val2, fit.Metal, 0.35f);
						}
					}
					val2.a = 1f;
					array[i * 64 + j] = val2;
				}
			}
			val.SetPixels(array);
			val.Apply(true);
			return val;
		}

		private static bool AddToCreature(Fit fit, Sadle? template, Material? material)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab(fit.Creature);
			Tameable val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Tameable>() : null);
			Transform val2 = (((Object)(object)prefab != (Object)null) ? Utils.FindChild(prefab.transform, fit.Bone, (IterativeSearchType)0) : null);
			if ((Object)(object)prefab == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || fit.Custom == null)
			{
				ServerPlugin.Log.LogWarning((object)("Sättel: " + fit.Creature + " ohne Zähm-Komponente oder Knochen " + fit.Bone + ", kein Sattel."));
				return false;
			}
			GameObject val3 = new GameObject("GC_Saddle")
			{
				layer = prefab.layer
			};
			val3.SetActive(false);
			val3.transform.SetParent(val2, false);
			val3.transform.position = prefab.transform.TransformPoint(fit.Origin);
			val3.transform.rotation = prefab.transform.rotation;
			Vector3 lossyScale = val2.lossyScale;
			val3.transform.localScale = new Vector3(fit.Scale / Mathf.Max(0.0001f, lossyScale.x), fit.Scale / Mathf.Max(0.0001f, lossyScale.y), fit.Scale / Mathf.Max(0.0001f, lossyScale.z));
			Mesh val4 = Model();
			if (val4 != null && (Object)(object)material != (Object)null)
			{
				val3.AddComponent<MeshFilter>().sharedMesh = val4;
				((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterial = material;
			}
			SphereCollider obj = val3.AddComponent<SphereCollider>();
			obj.center = new Vector3(0f, 0.12f, 0f);
			obj.radius = fit.Radius;
			GameObject val5 = new GameObject("GC_SaddleAttach")
			{
				layer = prefab.layer
			};
			val5.transform.SetParent(val3.transform, false);
			val5.transform.position = prefab.transform.TransformPoint(fit.Attach);
			val5.transform.rotation = prefab.transform.rotation;
			Sadle val6 = val3.AddComponent<Sadle>();
			if ((Object)(object)template != (Object)null)
			{
				val6.m_maxUseRange = template.m_maxUseRange;
				val6.m_detachOffset = template.m_detachOffset;
				val6.m_maxStamina = template.m_maxStamina;
				val6.m_runStaminaDrain = template.m_runStaminaDrain;
				val6.m_swimStaminaDrain = template.m_swimStaminaDrain;
				val6.m_staminaRegen = template.m_staminaRegen;
				val6.m_staminaRegenHungry = template.m_staminaRegenHungry;
				val6.m_drownEffects = template.m_drownEffects;
				val6.m_mountIcon = template.m_mountIcon;
				val6.m_hoverOffset = template.m_hoverOffset;
			}
			val6.m_hoverText = "$" + fit.Name;
			val6.m_attachPoint = val5.transform;
			val6.m_attachAnimation = fit.Animation;
			val.m_saddle = val6;
			val.m_saddleItem = fit.Custom.ItemDrop;
			val.m_dropSaddleOnDeath = true;
			val.m_dropSaddleOffset = new Vector3(0f, 1.5f * fit.Scale, 0f);
			return true;
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class SpeciesGameStartPatch
	{
		private static void Postfix()
		{
			Species.RegisterRpcs();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

GC_Tiere.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Leash;
using GC.Shared;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("GC_Tierarten")]
[assembly: InternalsVisibleTo("GC_WalkuerenTransport")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Tiere")]
[assembly: AssemblyTitle("GC_Tiere")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModTiere
{
	[BepInPlugin("gorduan.gc.tiere", "GC_Tiere", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.tiere");
			Care.Init(((BaseUnityPlugin)this).Config);
			Saddles.Init(((BaseUnityPlugin)this).Config);
			GC.Server.Leash.Plugin.Init(((BaseUnityPlugin)this).Config, val);
			Module.TakeOverOldSettings();
			Module.IsOn = () => GC.Server.Leash.Plugin.On || Care.Enabled.Value;
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("leash", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("leash_slip", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.SlipDistance, 1.0, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_interval", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.CheckInterval, 0.25, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_durability", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.DurabilityStep, 5.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_portal", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.PortalTravel, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_chase", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.ChaseDistance, 1.0, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_cmd_level", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.CommandMinLevel, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_cmd_cooldown", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.CommandCooldown, 5.0, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_loki", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.IllusionCooldown, 10.0, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("leash_whistles", (ConfigEntryBase)(object)GC.Server.Leash.Plugin.WhistlesEnabled, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Main("care", (ConfigEntryBase)(object)Care.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_radius", (ConfigEntryBase)(object)Care.Radius, 5.0, " m", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_feed", (ConfigEntryBase)(object)Care.FeedXp, 0.5, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_feed_cd", (ConfigEntryBase)(object)Care.FeedCooldown, 10.0, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_pet", (ConfigEntryBase)(object)Care.PetXp, 0.5, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_pet_cd", (ConfigEntryBase)(object)Care.PetCooldown, 60.0, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_tame", (ConfigEntryBase)(object)Care.TameXp, 2.5, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_breed", (ConfigEntryBase)(object)Care.BreedXp, 2.5, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_kill", (ConfigEntryBase)(object)Care.KillXp, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_delay", (ConfigEntryBase)(object)Care.FollowDelay, 0.5, " s", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_delay_level", (ConfigEntryBase)(object)Care.FollowDelayLevel, 5.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_xp", (ConfigEntryBase)(object)Care.AnimalXp, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_xp_factor", (ConfigEntryBase)(object)Care.AnimalXpFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("care_xp_kill", (ConfigEntryBase)(object)Care.AnimalKillXp, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}

		private void Update()
		{
			if (!Gc.IsHeadless)
			{
				Module.Guard("Tierleinen", (Action)GC.Server.Leash.Plugin.Update);
			}
		}
	}
	internal static class GcMod
	{
		public const string Id = "tiere";

		public const string Guid = "gorduan.gc.tiere";

		public const string Name = "GC_Tiere";

		public const string Version = "1.8.1";

		public const int Stufe = 5;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "tiere";
				val.Guid = "gorduan.gc.tiere";
				val.Name = "GC_Tiere";
				val.Version = "1.8.1";
				val.Stufe = 5;
				val.Seite = (GcSeite)2;
				val.Braucht = Array.Empty<string>();
				val.Partner = Array.Empty<string>();
				val.Fremd = new string[1] { "randyknapp.mods.epicloot" };
				val.AlteConfig = "gorduan.gc_server.cfg";
				val.Ausgleich = 5f;
				return val;
			}
		}
	}
}
namespace GC.Server.Leash
{
	internal static class Care
	{
		internal struct Stats
		{
			public float Damage;

			public float Speed;
		}

		internal sealed class Spawning
		{
			public Procreation? Parent;

			public Component? Source;

			public float Level;

			public bool Done;

			public Character? Born;

			public ItemDrop? Egg;

			public long Breeder;
		}

		internal const string SkillId = "gorduan.gc_server.tierpflege";

		internal static SkillType Skill = (SkillType)0;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<float> Radius = null;

		internal static ConfigEntry<float> FeedXp = null;

		internal static ConfigEntry<float> FeedCooldown = null;

		internal static ConfigEntry<float> PetXp = null;

		internal static ConfigEntry<float> PetCooldown = null;

		internal static ConfigEntry<float> TameXp = null;

		internal static ConfigEntry<float> BreedXp = null;

		internal static ConfigEntry<float> KillXp = null;

		internal static ConfigEntry<float> FollowDelay = null;

		internal static ConfigEntry<float> FollowDelayLevel = null;

		internal static ConfigEntry<bool> AnimalXp = null;

		internal static ConfigEntry<float> AnimalXpFactor = null;

		internal static ConfigEntry<float> AnimalKillXp = null;

		internal static readonly int SkillHash = StringExtensionMethods.GetStableHashCode("gc_care_skill");

		internal static readonly int LevelHash = StringExtensionMethods.GetStableHashCode("gc_care_level");

		internal static readonly int FeederHash = StringExtensionMethods.GetStableHashCode("gc_care_feeder");

		internal static readonly int DropperHash = StringExtensionMethods.GetStableHashCode("gc_care_dropper");

		internal static readonly int DropperSkillHash = StringExtensionMethods.GetStableHashCode("gc_care_dropper_skill");

		internal static readonly int FeederSkillHash = StringExtensionMethods.GetStableHashCode("gc_care_feeder_skill");

		private static readonly int HpBaseHash = StringExtensionMethods.GetStableHashCode("gc_care_hpbase");

		private static readonly int HpFactorHash = StringExtensionMethods.GetStableHashCode("gc_care_hpfactor");

		internal const string LevelKey = "gc_care_level";

		private const string PetKey = "gc_care_pet";

		internal const float MaxAnimalLevel = 150f;

		private const string XpRpc = "GC_CareXP";

		internal static readonly Dictionary<Character, Stats> Animals = new Dictionary<Character, Stats>();

		private static readonly Dictionary<string, float> FeedUntil = new Dictionary<string, float>();

		private static readonly List<string> Expired = new List<string>();

		private static float nextPublish;

		private static float nextAura;

		private static float lastAura;

		internal const float SkillShare = 0.5f;

		internal const float HealPercentPerLevel = 0.0001f;

		internal const float BonusShare = 5f / 12f;

		private static readonly Dictionary<string, bool> SummonedByPrefab = new Dictionary<string, bool>();

		internal static Spawning? Birth;

		internal static void Init(ConfigFile Config)
		{
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Expected O, but got Unknown
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			Enabled = Gc.BindSynced<bool>(Config, "8 - Animal Care", "Enabled", true, "Skill Tierpflege: Erfahrung durch Füttern, Zähmen, Streicheln, Züchten und Kämpfe deiner angeleinten Tiere; zahme Tiere in der Nähe werden stärker.", (AcceptableValueBase)null);
			Radius = Gc.BindSynced<float>(Config, "8 - Animal Care", "Radius", 30f, "Umkreis in Metern: So nah muss ein Spieler sein, damit sein Tierpflege-Bonus auf zahme Tiere wirkt (und aufs Zähmen).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f));
			FeedXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "FeedExperience", 1.5f, "Erfahrung, wenn ein Tier Futter frisst, das du fallen gelassen oder gepflückt hast (Jan, 19.10.2026: halbiert, vorher 3).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			FeedCooldown = Gc.BindSynced<float>(Config, "8 - Animal Care", "FeedCooldown", 60f, "Sekunden, bis Füttern desselben Tiers wieder Erfahrung gibt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3600f));
			PetXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "PetExperience", 2.5f, "Erfahrung fürs Streicheln eines zahmen Tiers (Jan, 19.10.2026: halbiert, vorher 5).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			PetCooldown = Gc.BindSynced<float>(Config, "8 - Animal Care", "PetCooldown", 1800f, "Sekunden, bis Streicheln desselben Tiers wieder Erfahrung gibt (Jan: 30 Minuten).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 86400f));
			TameXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "TameExperience", 15f, "Erfahrung, wenn ein Tier zahm wird (an den, dessen Futter es zuletzt fraß, sonst den nächsten Spieler; Jan, 19.10.2026: halbiert, vorher 30).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f));
			BreedXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "BreedExperience", 7.5f, "Erfahrung für den Züchter, wenn ein Junges geboren wird oder ein Ei gelegt wird (Jan, 19.10.2026: halbiert, vorher 15).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f));
			KillXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "KillXp", 2f, "Erfahrung, wenn ein Tier an deiner Leine etwas tötet (mal Stufe des Opfers: 1 Stern doppelt, 2 Sterne dreifach).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			FollowDelay = Gc.BindSynced<float>(Config, "8 - Animal Care", "FollowDelay", 2f, "Läuft der Halter los, zögert ein Tier an der Leine zufällig bis zu so vielen Sekunden (freier Wille), bevor es folgt. Je höher die Mischstufe (Tier-Stufe und halbe Tierpflege des Halters 1:2), desto kürzer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f));
			FollowDelayLevel = Gc.BindSynced<float>(Config, "8 - Animal Care", "FollowDelayLevel", 30f, "Ab dieser Mischstufe (Tier-Stufe + 2 × halbe Tierpflege des Halters, geteilt durch 3; Jan, 19.10.2026: Tierpflege zählt halb) folgt ein Tier an der Leine sofort; darunter zögert es anteilig.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 150f));
			AnimalXp = Gc.BindSynced<bool>(Config, "8 - Animal Care", "AnimalExperience", true, "Zahme Tiere sammeln im Kampf Erfahrung und steigen bis Stufe 150 auf. Je Stufe so viel wie Valheims Waffen-Skills (1 bei Stufe 1, 178 bei 50, 501 bei 100, 920 bei 150).", (AcceptableValueBase)null);
			AnimalXpFactor = Gc.BindSynced<float>(Config, "8 - Animal Care", "AnimalExperienceFactor", 1f, "Tempo der Tier-Erfahrung: 1 = wie Valheims Waffen-Skills, 2 = doppelt so schnell.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f));
			AnimalKillXp = Gc.BindSynced<float>(Config, "8 - Animal Care", "AnimalKillExperience", 5f, "Erfahrung fürs Töten, mal Stufe des Opfers (ohne Stern 5, 1 Stern 10, 2 Sterne 15). Dazu 1 je Angriff, der trifft, wie bei Waffen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f));
			Skill = SkillManager.Instance.AddSkill(new SkillConfig
			{
				Identifier = "gorduan.gc_server.tierpflege",
				Name = "$gcs_skill_care",
				Description = "$gcs_skill_care_desc",
				Icon = PawIcon(),
				IncreaseStep = 1f
			});
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CareLevelCommand());
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string[] array = new string[2] { "gcs_skill_care", "gcs_skill_care_desc" };
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				foreach (KeyValuePair<string, string> item in GcLoc.AllLanguages(text))
				{
					string key = item.Key;
					localization.AddTranslation(ref key, ref text, item.Value);
				}
			}
		}

		internal static void RegisterRpcs()
		{
			Animals.Clear();
			FeedUntil.Clear();
			Birth = null;
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.Register<float>("GC_CareXP", (Action<long, float>)RPC_Xp);
			}
			AnimalExperience.RegisterRpc();
		}

		private static void RPC_Xp(long sender, float amount)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && Enabled.Value && (int)Skill != 0)
			{
				((Character)localPlayer).RaiseSkill(Skill, Mathf.Clamp(amount, 0f, MaxGrant()));
			}
		}

		private static float MaxGrant()
		{
			return Mathf.Max(new float[5]
			{
				FeedXp.Value,
				PetXp.Value,
				TameXp.Value,
				BreedXp.Value,
				KillXp.Value * 6f
			});
		}

		internal static void Grant(long session, float amount)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled.Value || amount <= 0f || session == 0L || (int)Skill == 0)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && Links.Session(localPlayer) == session)
			{
				((Character)localPlayer).RaiseSkill(Skill, amount);
				return;
			}
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC(session, "GC_CareXP", new object[1] { amount });
			}
		}

		internal static float LevelOf(Player? player)
		{
			ZNetView val = (((Object)(object)player != (Object)null) ? ((Character)player).m_nview : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return 0f;
			}
			return val.GetZDO().GetFloat(SkillHash, 0f);
		}

		internal static float NearbyLevel(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Nearby(position, out var best);
			return best;
		}

		private static Player? Nearby(Vector3 position, out float best)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			best = 0f;
			Player result = null;
			float num = Radius.Value * Radius.Value;
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (!((Object)(object)allPlayer != (Object)null) || ((Character)allPlayer).IsDead())
				{
					continue;
				}
				Vector3 val = ((Component)allPlayer).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude <= num)
				{
					float num2 = LevelOf(allPlayer);
					if (num2 > best)
					{
						best = num2;
						result = allPlayer;
					}
				}
			}
			return result;
		}

		internal static Player? Caretaker(Character animal, ZDO zdo, out float level)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			long num = zdo.GetLong(Plugin.HolderHash, 0L);
			if (num == 0L)
			{
				num = zdo.GetLong(Illusions.IllusionHash, 0L);
			}
			Player val = ((num != 0L) ? Links.FindBySession(num) : null);
			if ((Object)(object)val != (Object)null)
			{
				level = LevelOf(val);
				return val;
			}
			return Nearby(((Component)animal).transform.position, out level);
		}

		internal static void Levels(Character animal, ZDO zdo, out float own, out float care)
		{
			float effectCap = SpeciesLink.EffectCap;
			own = Mathf.Clamp(zdo.GetFloat(LevelHash, 0f) * 0.5f, 0f, effectCap);
			Caretaker(animal, zdo, out var level);
			care = Mathf.Clamp(level, 0f, effectCap - own);
		}

		internal static float HealPerSecond(float level, float max)
		{
			return level * (0.05f + 4.1666666E-05f * max);
		}

		internal static bool InfoKeyHeld()
		{
			if (!Input.GetKey((KeyCode)308))
			{
				return Input.GetKey((KeyCode)307);
			}
			return true;
		}

		internal static bool ShowInfo(Player player, Tameable tame)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Character character = tame.m_character;
			ZNetView nview = tame.m_nview;
			if (!Enabled.Value || (int)Skill == 0 || (Object)(object)character == (Object)null || (Object)(object)nview == (Object)null || !nview.IsValid() || !tame.IsTamed() || Summoned(character))
			{
				return false;
			}
			ZDO zDO = nview.GetZDO();
			float effectCap = SpeciesLink.EffectCap;
			float num = Mathf.Clamp(zDO.GetFloat(LevelHash, 0f) * 0.5f, 0f, effectCap);
			float level;
			Player val = Caretaker(character, zDO, out level);
			float num2 = Mathf.Clamp(level, 0f, effectCap - num);
			float num3 = 5f / 12f * num;
			float num4 = 5f / 24f * num2;
			string hoverName = tame.GetHoverName();
			string text = (((Object)(object)val != (Object)null && level > 0f) ? GcLoc.Get("gcs_info_head", new object[3]
			{
				hoverName,
				val.GetPlayerName(),
				Mathf.FloorToInt(level)
			}) : GcLoc.Get("gcs_info_head_none", new object[1] { hoverName }));
			float maxHealth = character.GetMaxHealth();
			string text2 = GcLoc.Get("gcs_info_lines", new object[8]
			{
				Mathf.RoundToInt(2f * num3),
				Mathf.RoundToInt(2f * num4),
				Mathf.RoundToInt(num3),
				Mathf.RoundToInt(num4),
				Mathf.RoundToInt(0.5f * num3),
				Mathf.RoundToInt(0.5f * num4),
				Heal(num, maxHealth),
				Heal(num2, maxHealth)
			});
			if (AnimalExperience.On)
			{
				float num5 = zDO.GetFloat(LevelHash, 0f);
				text2 = text2 + "\n" + ((num5 >= SpeciesLink.MaxLevel(character)) ? GcLoc.Get("gcs_info_xp_max", Array.Empty<object>()) : GcLoc.Get("gcs_info_xp", new object[2]
				{
					Mathf.FloorToInt(zDO.GetFloat(AnimalExperience.XpHash, 0f)),
					Mathf.CeilToInt(AnimalExperience.Requirement(num5))
				}));
			}
			((Character)player).Message((MessageType)2, text + "\n" + text2, 0, (Sprite)null, false);
			return true;
		}

		private static string Heal(float level, float max)
		{
			return HealPerSecond(level, max).ToString("0.#");
		}

		internal static void Tick()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || (int)Skill == 0)
			{
				return;
			}
			float time = Time.time;
			if (time >= nextPublish)
			{
				nextPublish = time + 2f;
				Publish(localPlayer);
				Prune();
			}
			if (time < nextAura)
			{
				return;
			}
			float dt = ((lastAura > 0f) ? Mathf.Clamp(time - lastAura, 0f, 3f) : 0f);
			lastAura = time;
			nextAura = time + 1f;
			Animals.Clear();
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if ((Object)(object)allCharacter == (Object)null || allCharacter.IsPlayer() || !allCharacter.IsTamed() || allCharacter.IsDead())
				{
					continue;
				}
				ZNetView nview = allCharacter.m_nview;
				if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner() && !Summoned(allCharacter))
				{
					ZDO zDO = nview.GetZDO();
					float num = LeashBonus(zDO);
					float own = 0f;
					float care = 0f;
					if (Enabled.Value)
					{
						Levels(allCharacter, zDO, out own, out care);
					}
					float num2 = 5f / 12f * (own + 0.5f * care);
					Apply(allCharacter, zDO, num, num2, own + care, dt);
					if (num > 0f || num2 > 0f)
					{
						Animals[allCharacter] = new Stats
						{
							Damage = num + num2 / 100f,
							Speed = 0.5f * num2 / 100f
						};
					}
				}
			}
		}

		internal static bool Summoned(Character animal)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			string prefabName = Utils.GetPrefabName(((Component)animal).gameObject);
			if (!SummonedByPrefab.TryGetValue(prefabName, out var value))
			{
				Tameable component = ((Component)animal).GetComponent<Tameable>();
				value = (Object)(object)component != (Object)null && (component.m_unsummonDistance > 0f || component.m_unsummonOnOwnerLogoutSeconds > 0f || (int)component.m_levelUpOwnerSkill > 0);
				SummonedByPrefab[prefabName] = value;
			}
			return value;
		}

		private static void Publish(Player local)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = ((Character)local).m_nview;
			if (!((Object)(object)nview == (Object)null) && nview.IsValid())
			{
				float num = (Enabled.Value ? ((Character)local).GetSkillLevel(Skill) : 0f);
				ZDO zDO = nview.GetZDO();
				if (Mathf.Abs(zDO.GetFloat(SkillHash, 0f) - num) > 0.01f)
				{
					zDO.Set(SkillHash, num);
				}
			}
		}

		private static float LeashBonus(ZDO zdo)
		{
			if (!Plugin.On)
			{
				return 0f;
			}
			float num = zdo.GetFloat(Plugin.BonusHash, 0f);
			if (num > 0f && zdo.GetLong(Plugin.HolderHash, 0L) == 0L && !Posts.IsTied(zdo))
			{
				zdo.Set(Plugin.BonusHash, 0f);
				return 0f;
			}
			return num;
		}

		private static void Apply(Character animal, ZDO zdo, float leash, float level, float healLevel, float dt)
		{
			if ((Bonds.AnyFainted && Bonds.IsFainted(animal)) || animal.GetHealth() <= 0f)
			{
				return;
			}
			float num = 1f + leash + 2f * level / 100f;
			float num2 = animal.GetMaxHealth();
			float num3 = zdo.GetFloat(HpBaseHash, 0f);
			float num4 = zdo.GetFloat(HpFactorHash, 1f);
			float num5 = ((num3 > 0f && Mathf.Abs(num2 - num3 * num4) <= Mathf.Max(1f, num2 * 0.01f)) ? num3 : num2);
			if (num5 <= 0f)
			{
				return;
			}
			float num6 = num5 * num;
			if (Mathf.Abs(num2 - num6) > Mathf.Max(0.5f, num6 * 0.005f))
			{
				float num7 = ((num2 > 0f) ? Mathf.Clamp01(animal.GetHealth() / num2) : 1f);
				animal.SetMaxHealth(num6);
				animal.SetHealth(Mathf.Max(1f, num7 * num6));
				num2 = num6;
			}
			if (num <= 1.0001f)
			{
				if (num3 > 0f)
				{
					zdo.Set(HpBaseHash, 0f);
					zdo.Set(HpFactorHash, 1f);
				}
			}
			else
			{
				if (Mathf.Abs(num3 - num5) > 0.01f)
				{
					zdo.Set(HpBaseHash, num5);
				}
				if (Mathf.Abs(num4 - num) > 0.0001f)
				{
					zdo.Set(HpFactorHash, num);
				}
			}
			if (healLevel > 0f && dt > 0f && animal.GetHealth() < num2)
			{
				animal.Heal(HealPerSecond(healLevel, num2) * dt, false);
			}
		}

		private static void Prune()
		{
			if (FeedUntil.Count == 0)
			{
				return;
			}
			Expired.Clear();
			float time = Time.time;
			foreach (KeyValuePair<string, float> item in FeedUntil)
			{
				if (item.Value <= time)
				{
					Expired.Add(item.Key);
				}
			}
			foreach (string item2 in Expired)
			{
				FeedUntil.Remove(item2);
			}
		}

		internal static void Fed(Tameable tame, long dropper, float skill)
		{
			ZNetView nview = tame.m_nview;
			if (dropper == 0L || (Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return;
			}
			ZDO zDO = nview.GetZDO();
			if (nview.IsOwner())
			{
				bool flag = zDO.GetLong(FeederHash, 0L) != dropper;
				if (flag)
				{
					zDO.Set(FeederHash, dropper);
				}
				if ((skill >= 0f) ? (Mathf.Abs(zDO.GetFloat(FeederSkillHash, -1f) - skill) > 0.001f) : flag)
				{
					zDO.Set(FeederSkillHash, skill);
				}
			}
			if (Enabled.Value && !(FeedXp.Value <= 0f))
			{
				string key = ((ZDOID)(ref zDO.m_uid)).UserID + ":" + ((ZDOID)(ref zDO.m_uid)).ID + ":" + dropper;
				if (!FeedUntil.TryGetValue(key, out var value) || !(Time.time < value))
				{
					FeedUntil[key] = Time.time + FeedCooldown.Value;
					Grant(dropper, FeedXp.Value);
				}
			}
		}

		internal static void Pet(Player player, Tameable tame)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = tame.m_nview;
			if (Enabled.Value && !(PetXp.Value <= 0f) && !((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)ZNet.instance == (Object)null) && (int)Skill != 0)
			{
				double timeSeconds = ZNet.instance.GetTimeSeconds();
				string key = AnimalKey(nview.GetZDO());
				Dictionary<string, double> dictionary = ReadPets(player, timeSeconds);
				if (!dictionary.TryGetValue(key, out var value) || !(value > timeSeconds))
				{
					dictionary[key] = timeSeconds + (double)PetCooldown.Value;
					WritePets(player, dictionary);
					((Character)player).RaiseSkill(Skill, PetXp.Value);
				}
			}
		}

		private static string AnimalKey(ZDO zdo)
		{
			long num = zdo.GetLong(ZDOVars.s_spawnTime, 0L);
			if (num == 0L)
			{
				return ((ZDOID)(ref zdo.m_uid)).UserID + ":" + ((ZDOID)(ref zdo.m_uid)).ID;
			}
			return zdo.GetPrefab().ToString(CultureInfo.InvariantCulture) + ":" + num.ToString(CultureInfo.InvariantCulture);
		}

		private static Dictionary<string, double> ReadPets(Player player, double now)
		{
			Dictionary<string, double> dictionary = new Dictionary<string, double>();
			if (player.m_customData == null || !player.m_customData.TryGetValue("gc_care_pet", out var value) || string.IsNullOrEmpty(value))
			{
				return dictionary;
			}
			double num = now + (double)PetCooldown.Value + 1.0;
			string[] array = value.Split(';');
			foreach (string text in array)
			{
				int num2 = text.LastIndexOf('=');
				if (num2 > 0 && double.TryParse(text.Substring(num2 + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result > now && result <= num)
				{
					dictionary[text.Substring(0, num2)] = result;
				}
			}
			return dictionary;
		}

		private static void WritePets(Player player, Dictionary<string, double> list)
		{
			if (player.m_customData == null)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, double> item in list)
			{
				stringBuilder.Append((stringBuilder.Length > 0) ? ";" : "").Append(item.Key).Append('=')
					.Append(item.Value.ToString("0", CultureInfo.InvariantCulture));
			}
			player.m_customData["gc_care_pet"] = stringBuilder.ToString();
		}

		internal static void MarkDropper(ItemDrop item, long session, float skill)
		{
			if (session != 0L && !((Object)(object)item == (Object)null) && !((Object)(object)item.m_nview == (Object)null) && item.m_nview.IsValid() && item.m_nview.IsOwner())
			{
				ZDO zDO = item.m_nview.GetZDO();
				zDO.Set(DropperHash, session);
				zDO.Set(DropperSkillHash, Mathf.Clamp(skill, 0f, 100f));
			}
		}

		internal static float SkillOfSession(long session)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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 (session == 0L || !Enabled.Value || (int)Skill == 0)
			{
				return 0f;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && Links.Session(localPlayer) == session)
			{
				return ((Character)localPlayer).GetSkillLevel(Skill);
			}
			Player val = Links.FindBySession(session);
			if ((Object)(object)val != (Object)null)
			{
				return LevelOf(val);
			}
			if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null)
			{
				return 0f;
			}
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				ZDOID characterID = player.m_characterID;
				if (((ZDOID)(ref characterID)).UserID == session)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(player.m_characterID);
					return (zDO != null) ? zDO.GetFloat(SkillHash, 0f) : 0f;
				}
			}
			return 0f;
		}

		internal static long CaretakerOf(Character animal, ZDO zdo, float range)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			long num = zdo.GetLong(FeederHash, 0L);
			if (num != 0L && (Object)(object)Links.FindBySession(num) != (Object)null)
			{
				return num;
			}
			return Links.Session(Player.GetClosestPlayer(((Component)animal).transform.position, range));
		}

		internal static void OnBorn(Character born)
		{
			Spawning birth = Birth;
			if (birth == null || birth.Done || (Object)(object)born == (Object)null || ((Object)(object)birth.Source != (Object)null && (Object)(object)((Component)born).gameObject == (Object)(object)birth.Source.gameObject) || ((Object)(object)birth.Parent != (Object)null && (Object)(object)((Component)born).gameObject == (Object)(object)((Component)birth.Parent).gameObject))
			{
				return;
			}
			ZNetView nview = born.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
			{
				return;
			}
			birth.Done = true;
			birth.Born = born;
			if (birth.Source is Growup)
			{
				Character component = birth.Source.GetComponent<Character>();
				if (component != null)
				{
					Young.CopyState(component, born);
				}
			}
			long breeder = 0L;
			float num = (((Object)(object)birth.Parent != (Object)null) ? BirthLevel(birth.Parent, out breeder) : birth.Level);
			birth.Breeder = breeder;
			if (num > 0f)
			{
				nview.GetZDO().Set(LevelHash, Mathf.Min(num, SpeciesLink.MaxLevel(born)));
			}
			if ((Object)(object)birth.Parent != (Object)null)
			{
				Grant(breeder, BreedXp.Value);
			}
		}

		internal static void OnEgg(ItemDrop egg)
		{
			Spawning birth = Birth;
			if (!((Object)(object)birth?.Parent == (Object)null) && !birth.Done && !((Object)(object)egg == (Object)null) && !((Object)(object)egg.m_nview == (Object)null) && egg.m_nview.IsValid() && egg.m_nview.IsOwner())
			{
				birth.Done = true;
				birth.Egg = egg;
				long breeder;
				float num = BirthLevel(birth.Parent, out breeder);
				birth.Breeder = breeder;
				if (num > 0f)
				{
					egg.m_itemData.m_customData["gc_care_level"] = Mathf.Min(num, SpeciesLink.MaxLevel(birth.Parent.m_character)).ToString("0.##", CultureInfo.InvariantCulture);
					egg.Save();
				}
				Grant(breeder, BreedXp.Value);
			}
		}

		private static float BirthLevel(Procreation parent, out long breeder)
		{
			breeder = 0L;
			Character character = parent.m_character;
			if ((Object)(object)character == (Object)null || (Object)(object)parent.m_nview == (Object)null || !parent.m_nview.IsValid() || !Enabled.Value)
			{
				return 0f;
			}
			ZDO zDO = parent.m_nview.GetZDO();
			float num = zDO.GetFloat(LevelHash, 0f);
			float? mateLevel = GcHooks.GetMateLevel(parent);
			float num2 = num;
			if (mateLevel.HasValue)
			{
				num2 = mateLevel.Value;
			}
			else
			{
				string prefabName = Utils.GetPrefabName(((Object)(object)parent.m_seperatePartner != (Object)null) ? parent.m_seperatePartner : ((Component)character).gameObject);
				Character val = MateOf(character, prefabName, Mathf.Max(parent.m_partnerCheckRange, 3f));
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_nview != (Object)null && val.m_nview.IsValid())
				{
					num2 = val.m_nview.GetZDO().GetFloat(LevelHash, 0f);
				}
			}
			float num3 = Random.Range(0.75f * (num + num2) * 0.5f, Mathf.Max(num, num2));
			float num4 = Random.Range(0f, BreederSkill(zDO, out breeder) / 4f);
			return Mathf.Clamp(num3 + num4, 0f, SpeciesLink.MaxLevel(character));
		}

		private static float BreederSkill(ZDO zdo, out long breeder)
		{
			breeder = zdo.GetLong(FeederHash, 0L);
			if (breeder == 0L)
			{
				return 0f;
			}
			float num = zdo.GetFloat(FeederSkillHash, -1f);
			return Mathf.Clamp((num >= 0f) ? num : SkillOfSession(breeder), 0f, 100f);
		}

		private static Character? MateOf(Character mother, string kind, float range)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			Character result = null;
			float num = range * range;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)mother) && allCharacter.IsTamed() && !allCharacter.IsDead() && !Illusions.IsIllusion(allCharacter) && !(Utils.GetPrefabName(((Component)allCharacter).gameObject) != kind))
				{
					Vector3 val = ((Component)allCharacter).transform.position - ((Component)mother).transform.position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude <= num)
					{
						num = sqrMagnitude;
						result = allCharacter;
					}
				}
			}
			return result;
		}

		internal static float Hesitation(Link link)
		{
			//IL_0023: 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)
			if (!Enabled.Value || FollowDelay.Value <= 0f)
			{
				return 0f;
			}
			float num = (((int)Skill != 0 && (Object)(object)link.Holder != (Object)null) ? ((Character)link.Holder).GetSkillLevel(Skill) : 0f);
			float num2 = (AnimalLevelExact(link.Tame) + 1f * num) / 3f;
			float num3 = FollowDelay.Value * Mathf.Clamp01(1f - num2 / Mathf.Max(1f, FollowDelayLevel.Value));
			if (!(num3 > 0f))
			{
				return 0f;
			}
			return Random.Range(0f, num3);
		}

		internal static int AnimalLevel(Tameable tame)
		{
			return Mathf.FloorToInt(AnimalLevelExact(tame));
		}

		internal static float AnimalLevelExact(Tameable? tame)
		{
			ZNetView val = (((Object)(object)tame != (Object)null) ? tame.m_nview : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return 0f;
			}
			return val.GetZDO().GetFloat(LevelHash, 0f);
		}

		internal static string WithLevel(Tameable tame, string text)
		{
			int num = AnimalLevel(tame);
			if (num < 1)
			{
				return text;
			}
			string name = tame.GetName();
			if (name.Length <= 0 || !text.StartsWith(name, StringComparison.Ordinal))
			{
				return text;
			}
			return name + " (Lvl " + num + ")" + text.Substring(name.Length);
		}

		internal static float EggLevel(ItemData? item)
		{
			if (item?.m_customData == null || !item.m_customData.TryGetValue("gc_care_level", out var value) || !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return 0f;
			}
			return result;
		}

		private static Sprite PawIcon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: 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)
			//IL_01be: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.93f, 0.86f, 0.72f, 1f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.35f, 0.24f, 0.14f, 1f);
			(Vector2, Vector2)[] array = new(Vector2, Vector2)[5]
			{
				(new Vector2(32f, 22f), new Vector2(14f, 12f)),
				(new Vector2(14f, 38f), new Vector2(6f, 7.5f)),
				(new Vector2(25f, 48f), new Vector2(6f, 7.5f)),
				(new Vector2(39f, 48f), new Vector2(6f, 7.5f)),
				(new Vector2(50f, 38f), new Vector2(6f, 7.5f))
			};
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					Color val5 = val2;
					(Vector2, Vector2)[] array2 = array;
					for (int k = 0; k < array2.Length; k++)
					{
						(Vector2, Vector2) tuple = array2[k];
						Vector2 item = tuple.Item1;
						Vector2 item2 = tuple.Item2;
						float num = ((float)j + 0.5f - item.x) / item2.x;
						float num2 = ((float)i + 0.5f - item.y) / item2.y;
						float num3 = num * num + num2 * num2;
						if (num3 <= 1f)
						{
							val5 = ((num3 > 0.72f) ? val4 : val3);
							break;
						}
					}
					val.SetPixel(j, i, val5);
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}
	}
	internal sealed class CareLevelCommand : ConsoleCommand
	{
		public override string Name => "gc_tierstufe";

		public override string Help => "GC_Server Tierpflege: Zucht-Stufe (0–150) des zahmen Tiers unter dem Fadenkreuz setzen (Test)";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			Player localPlayer = Player.m_localPlayer;
			Character val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetHoverCreature() : null);
			Tameable val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Tameable>() : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || !val.IsTamed() || (Object)(object)val2.m_nview == (Object)null || !val2.m_nview.IsValid())
			{
				Console.instance.Print("gc_tierstufe: Schau ein zahmes Tier an.");
				return;
			}
			if (args.Length < 1 || !float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				Console.instance.Print($"Aufruf: gc_tierstufe <0 bis {SpeciesLink.MaxLevel(val):0}>");
				return;
			}
			result = Mathf.Clamp(result, 0f, SpeciesLink.MaxLevel(val));
			if (!val2.m_nview.IsOwner())
			{
				val2.m_nview.ClaimOwnership();
			}
			val2.m_nview.GetZDO().Set(Care.LevelHash, result);
			Console.instance.Print($"gc_tierstufe: {val2.GetHoverName()} hat jetzt Zucht-Stufe {result:0}.");
		}
	}
	[HarmonyPatch(typeof(Humanoid), "DropItem")]
	internal static class CareDropPatch
	{
		internal static bool Dropping;

		private static void Prefix(Humanoid __instance)
		{
			Dropping = (Object)(object)__instance == (Object)(object)Player.m_localPlayer;
		}

		private static void Finalizer()
		{
			Dropping = false;
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "DropItem")]
	internal static class CareDropMarkPatch
	{
		private static void Postfix(ItemDrop __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (CareDropPatch.Dropping && (Object)(object)localPlayer != (Object)null)
			{
				long session = Links.Session(localPlayer);
				Care.MarkDropper(__result, session, Care.SkillOfSession(session));
			}
		}
	}
	[HarmonyPatch(typeof(Pickable), "RPC_Pick")]
	internal static class CarePickPatch
	{
		internal static long Picker;

		internal static float Skill;

		private static void Prefix(long sender)
		{
			Picker = sender;
			Skill = Care.SkillOfSession(sender);
		}

		private static void Finalizer()
		{
			Picker = 0L;
		}
	}
	[HarmonyPatch(typeof(PickableItem), "RPC_Pick")]
	internal static class CarePickItemPatch
	{
		private static void Prefix(long sender)
		{
			CarePickPatch.Picker = sender;
			CarePickPatch.Skill = Care.SkillOfSession(sender);
		}

		private static void Finalizer()
		{
			CarePickPatch.Picker = 0L;
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[]
	{
		typeof(ItemDrop),
		typeof(bool)
	})]
	internal static class CarePickMarkPatch
	{
		private static void Postfix(ItemDrop item)
		{
			if (CarePickPatch.Picker != 0L)
			{
				Care.MarkDropper(item, CarePickPatch.Picker, CarePickPatch.Skill);
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "RemoveOne")]
	internal static class CareConsumeSourcePatch
	{
		internal static ItemDrop? Item;

		internal static long Dropper;

		internal static float DropperSkill;

		private static void Prefix(ItemDrop __instance)
		{
			Item = __instance;
			ZDO val = (((Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid()) ? __instance.m_nview.GetZDO() : null);
			Dropper = ((val != null) ? val.GetLong(Care.DropperHash, 0L) : 0);
			DropperSkill = ((val != null) ? val.GetFloat(Care.DropperSkillHash, -1f) : (-1f));
		}
	}
	[HarmonyPatch(typeof(Tameable), "OnConsumedItem")]
	internal static class CareFeedPatch
	{
		private static void Postfix(Tameable __instance, ItemDrop item)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)CareConsumeSourcePatch.Item == (Object)(object)item)
			{
				Care.Fed(__instance, CareConsumeSourcePatch.Dropper, CareConsumeSourcePatch.DropperSkill);
			}
			CareConsumeSourcePatch.Item = null;
		}
	}
	[HarmonyPatch(typeof(Tameable), "Tame")]
	internal static class CareTamePatch
	{
		private static void Prefix(Tameable __instance, out bool __state)
		{
			__state = __instance.IsTamed();
		}

		private static void Postfix(Tameable __instance, bool __state)
		{
			if (!__state && __instance.IsTamed() && !((Object)(object)__instance.m_character == (Object)null) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner())
			{
				Care.Grant(Care.CaretakerOf(__instance.m_character, __instance.m_nview.GetZDO(), 30f), Care.TameXp.Value);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	internal static class CareKillPatch
	{
		private static void Prefix(Character __instance)
		{
			if (!Care.Enabled.Value || __instance.IsPlayer() || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner())
			{
				return;
			}
			HitData lastHit = __instance.m_lastHit;
			Character val = ((lastHit != null) ? lastHit.GetAttacker() : null);
			if (!((Object)(object)val == (Object)null) && !val.IsPlayer() && val.IsTamed() && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid())
			{
				if (!__instance.IsTamed())
				{
					AnimalExperience.Give(val, Care.AnimalKillXp.Value * (float)Mathf.Max(1, __instance.GetLevel()));
				}
				ZDO zDO = val.m_nview.GetZDO();
				long num = zDO.GetLong(Plugin.HolderHash, 0L);
				if (num == 0L)
				{
					num = zDO.GetLong(Illusions.IllusionHash, 0L);
				}
				if (num != 0L)
				{
					Care.Grant(num, Care.KillXp.Value * (float)Mathf.Max(1, __instance.GetLevel()));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "Interact")]
	internal static class CarePetPatch
	{
		private static void Postfix(Tameable __instance, Humanoid user, bool hold, bool alt, bool __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!(!__result || hold || alt) && !((Object)(object)localPlayer == (Object)null) && !((Object)(object)user != (Object)(object)localPlayer) && __instance.IsTamed() && Control.Held(localPlayer) == null && (!((Object)(object)__instance.m_character != (Object)null) || (!Illusions.IsIllusion(__instance.m_character) && !Care.Summoned(__instance.m_character))))
			{
				Care.Pet(localPlayer, __instance);
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	internal static class CareInfoHoverPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(Tameable __instance, ref string __result)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Character character = __instance.m_character;
			if (!string.IsNullOrEmpty(__result) && Care.Enabled.Value && (int)Care.Skill != 0 && !((Object)(object)character == (Object)null) && __instance.IsTamed() && !Illusions.IsIllusion(character) && !Care.Summoned(character))
			{
				__result = __result + "\n" + Localization.instance.Localize(GcLoc.Get("gcs_hover_info", Array.Empty<object>()));
			}
		}
	}
	[HarmonyPatch(typeof(SkillsDialog), "Setup")]
	internal static class CareSkillTextPatch
	{
		private static void Prefix(Player player)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && (int)Care.Skill != 0 && Localization.instance != null)
			{
				string text = GcLoc.Get("gcs_skill_care_desc", Array.Empty<object>());
				if (Care.Enabled.Value)
				{
					float skillLevel = ((Character)player).GetSkillLevel(Care.Skill);
					float num = 5f / 24f * skillLevel;
					text = text + "\n" + GcLoc.Get("gcs_skill_care_now", new object[6]
					{
						Mathf.RoundToInt(2f * num),
						Mathf.RoundToInt(num),
						Mathf.RoundToInt(0.5f * num),
						(0.05f * skillLevel).ToString("0.#"),
						(0.0041666664f * skillLevel).ToString("0.##"),
						(1f + 2f * skillLevel / 100f).ToString("0.#")
					});
				}
				Localization.instance.AddWord("gcs_skill_care_desc", text);
				Localization.instance.m_cache.EvictAll();
			}
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class CareProcreatePatch
	{
		private static void Prefix(Procreation __instance)
		{
			if ((Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner())
			{
				Care.Birth = new Care.Spawning
				{
					Parent = __instance
				};
			}
		}

		private static void Finalizer()
		{
			Care.Birth = null;
		}
	}
	[HarmonyPatch(typeof(Growup), "GrowUpdate")]
	internal static class CareGrowupPatch
	{
		private static void Prefix(Growup __instance)
		{
			ZNetView nview = __instance.m_nview;
			Care.Birth = (((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner()) ? new Care.Spawning
			{
				Source = (Component?)(object)__instance,
				Level = nview.GetZDO().GetFloat(Care.LevelHash, 0f)
			} : null);
		}

		private static void Postfix(Growup __instance)
		{
			Character val = Care.Birth?.Born;
			if ((Object)(object)val != (Object)null)
			{
				Young.Relink(((Component)__instance).GetComponent<Character>(), val);
			}
		}

		private static void Finalizer()
		{
			Care.Birth = null;
		}
	}
	[HarmonyPatch(typeof(EggGrow), "GrowUpdate")]
	internal static class CareEggPatch
	{
		private static void Prefix(EggGrow __instance)
		{
			float num = Care.EggLevel(((Object)(object)__instance.m_item != (Object)null) ? __instance.m_item.m_itemData : null);
			Care.Birth = ((num > 0f) ? new Care.Spawning
			{
				Source = (Component?)(object)__instance,
				Level = num
			} : null);
		}

		private static void Finalizer()
		{
			Care.Birth = null;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class CareBornPatch
	{
		private static void Postfix(Character __instance)
		{
			if (Care.Birth != null && !__instance.IsPlayer())
			{
				Care.OnBorn(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	internal static class CareEggLaidPatch
	{
		private static void Postfix(ItemDrop __instance)
		{
			if ((Object)(object)Care.Birth?.Parent != (Object)null)
			{
				Care.OnEgg(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "GetHoverName")]
	internal static class CareNamePatch
	{
		private static void Postfix(Tameable __instance, ref string __result)
		{
			int num = Care.AnimalLevel(__instance);
			if (num >= 1)
			{
				__result = __result + " (Lvl " + num + ")";
			}
		}
	}
	[HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")]
	internal static class CareSpeedPatch
	{
		private static void Postfix(SEMan __instance, ref float speed)
		{
			if (Care.Animals.Count > 0 && (Object)(object)__instance.m_character != (Object)null && Care.Animals.TryGetValue(__instance.m_character, out var value) && value.Speed > 0f)
			{
				speed *= 1f + value.Speed;
			}
		}
	}
	[HarmonyPatch(typeof(SEMan), "ModifyAttack")]
	internal static class CareAttackPatch
	{
		private static void Postfix(SEMan __instance, ref HitData hitData)
		{
			if (Care.Animals.Count > 0 && (Object)(object)__instance.m_character != (Object)null && Care.Animals.TryGetValue(__instance.m_character, out var value) && value.Damage > 0f)
			{
				((DamageTypes)(ref hitData.m_damage)).Modify(1f + value.Damage);
			}
		}
	}
	[HarmonyPatch(typeof(Tameable), "DecreaseRemainingTime")]
	internal static class CareTamingPatch
	{
		private static void Prefix(Tameable __instance, ref float time)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (Care.Enabled.Value)
			{
				float num = Care.NearbyLevel(((Component)__instance).transform.position);
				if (num > 0f)
				{
					time *= 1f + 2f * num / 100f;
				}
			}
		}
	}
	internal static class EggStacks
	{
		private static readonly Dictionary<string, bool> EggByPrefab = new Dictionary<string, bool>();

		internal static ItemData? Adding;

		internal static bool IsEgg(ItemData? item)
		{
			GameObject val = item?.m_dropPrefab;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!EggByPrefab.TryGetValue(((Object)val).name, out var value))
			{
				value = (Object)(object)val.GetComponent<EggGrow>() != (Object)null;
				EggByPrefab[((Object)val).name] = value;
			}
			return value;
		}

		internal static bool Mismatch(ItemData? a, ItemData? b)
		{
			if (a != null && b != null && IsEgg(a))
			{
				return Mathf.Abs(Care.EggLevel(a) - Care.EggLevel(b)) > 0.01f;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class EggAddPatch
	{
		private static void Prefix(ItemData item)
		{
			EggStacks.Adding = (EggStacks.IsEgg(item) ? item : null);
		}

		private static void Finalizer()
		{
			EggStacks.Adding = null;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(Vector2i)
	})]
	internal static class EggAddAtPatch
	{
		private static void Prefix(ItemData item)
		{
			EggStacks.Adding = (EggStacks.IsEgg(item) ? item : null);
		}

		private static void Finalizer()
		{
			EggStacks.Adding = null;
		}
	}
	[HarmonyPatch(typeof(Inventory), "FindFreeStackItem")]
	internal static class EggFreeStackPatch
	{
		private static void Postfix(Inventory __instance, string name, int quality, float worldLevel, ref ItemData? __result)
		{
			ItemData adding = EggStacks.Adding;
			if (adding == null || __result == null || !EggStacks.Mismatch(adding, __result))
			{
				return;
			}
			__result = null;
			foreach (ItemData item in __instance.m_inventory)
			{
				if (item.m_shared.m_name == name && item.m_quality == quality && item.m_stack < item.m_shared.m_maxStackSize && (float)item.m_worldLevel == worldLevel && !EggStacks.Mismatch(adding, item))
				{
					__result = item;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "IsSameType")]
	internal static class EggSameTypePatch
	{
		private static void Postfix(ItemData __instance, ItemData other, ref bool __result)
		{
			if (__result && EggStacks.Mismatch(__instance, other))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "AutoStackItems")]
	internal static class EggAutoStackPatch
	{
		private static bool Prefix(ItemDrop __instance)
		{
			if (Care.Enabled.Value)
			{
				return !EggStacks.IsEgg(__instance.m_itemData);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class EggTooltipPatch
	{
		private static void Postfix(ItemData item, ref string __result)
		{
			float num = ((item != null && EggStacks.IsEgg(item)) ? Care.EggLevel(item) : 0f);
			if (num >= 1f)
			{
				__result = __result + "\n" + GcLoc.Get("gcs_egg_level", new object[1] { Mathf.FloorToInt(num) });
			}
		}
	}
	internal static class Countdown
	{
		private struct Sample
		{
			public float Remaining;

			public float Since;
		}

		private const float ShowRange = 20f;

		private const float Step = 3f;

		private static readonly Dictionary<Tameable, Sample> Samples = new Dictionary<Tameable, Sample>();

		private static readonly HashSet<GameObject> Shown = new HashSet<GameObject>();

		private static readonly HashSet<GameObject> Seen = new HashSet<GameObject>();

		private static readonly List<GameObject> Stale = new List<GameObject>();

		private static readonly List<Tameable> Forget = new List<Tameable>();

		private static readonly List<Player> InRange = new List<Player>();

		private static float next;

		private static bool reported;

		private static readonly Dictionary<ZDOID, long> Celebrated = new Dictionary<ZDOID, long>();

		private static EffectList? levelUpLocal;

		internal static void Tick()
		{
			//IL_01ca: 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_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < next)
			{
				return;
			}
			next = Time.time + 0.5f;
			Player localPlayer = Player.m_localPlayer;
			Chat instance = Chat.instance;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				if ((Object)(object)instance != (Object)null)
				{
					foreach (GameObject item in Shown)
					{
						if ((Object)(object)item != (Object)null)
						{
							instance.ClearNpcText(item);
						}
					}
				}
				Shown.Clear();
				Samples.Clear();
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			Seen.Clear();
			Vector3 val;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if ((Object)(object)allCharacter == (Object)null || allCharacter.IsPlayer() || allCharacter.IsDead())
				{
					continue;
				}
				val = ((Component)allCharacter).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude > 400f)
				{
					continue;
				}
				try
				{
					string text = (allCharacter.IsTamed() ? (LevelUp(localPlayer, allCharacter) ?? Breeding(allCharacter)) : Taming(allCharacter));
					if (text != null)
					{
						Show(instance, ((Component)allCharacter).gameObject, allCharacter.GetTopPoint().y - ((Component)allCharacter).transform.position.y + 0.4f, text);
					}
				}
				catch (Exception e)
				{
					Report(e);
				}
			}
			foreach (ItemDrop s_instance in ItemDrop.s_instances)
			{
				if ((Object)(object)s_instance == (Object)null)
				{
					continue;
				}
				val = ((Component)s_instance).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude > 400f)
				{
					continue;
				}
				try
				{
					string text2 = Hatching(s_instance);
					if (text2 != null)
					{
						Show(instance, ((Component)s_instance).gameObject, 0.6f, text2);
					}
				}
				catch (Exception e2)
				{
					Report(e2);
				}
			}
			Stale.Clear();
			foreach (GameObject item2 in Shown)
			{
				if (!Seen.Contains(item2))
				{
					Stale.Add(item2);
				}
			}
			foreach (GameObject item3 in Stale)
			{
				Shown.Remove(item3);
				if ((Object)(object)item3 != (Object)null)
				{
					instance.ClearNpcText(item3);
				}
			}
			Forget.Clear();
			foreach (KeyValuePair<Tameable, Sample> sample in Samples)
			{
				Tameable key = sample.Key;
				if ((Object)(object)key == (Object)null || !Seen.Contains(((Component)key).gameObject))
				{
					Forget.Add(sample.Key);
				}
			}
			foreach (Tameable item4 in Forget)
			{
				Samples.Remove(item4);
			}
		}

		private static void Report(Exception e)
		{
			if (!reported)
			{
				reported = true;
				Plugin.Log.LogWarning((object)("Countdown: " + e));
			}
		}

		private static void Show(Chat chat, GameObject go, float height, string text)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Seen.Add(go);
			Shown.Add(go);
			NpcText val = chat.FindNpcText(go);
			if (val == null)
			{
				chat.SetNpcText(go, Vector3.up * height, 30f, 0f, "", text, false);
			}
			else if (val.m_text != text)
			{
				val.m_text = text;
				val.UpdateText();
			}
		}

		private static string? Taming(Character animal)
		{
			//IL_0008: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			Tameable component = ((Component)animal).GetComponent<Tameable>();
			GcTaming val = SpeciesLink.Taming(animal);
			if ((int)val == 1)
			{
				return null;
			}
			BaseAI val2 = (BaseAI)(((Object)(object)component != (Object)null && (Object)(object)component.m_monsterAI != (Object)null) ? ((object)component.m_monsterAI) : ((object)(((int)val == 2) ? animal.GetBaseAI() : null)));
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid() || (Object)(object)val2 == (Object)null)
			{
				return null;
			}
			float remainingTime = component.GetRemainingTime();
			bool flag = component.IsHungry();
			if (flag && remainingTime >= component.m_tamingTime - 0.01f)
			{
				return null;
			}
			float time = Time.time;
			if (!Samples.TryGetValue(component, out var value) || Mathf.Abs(value.Remaining - remainingTime) > 0.001f)
			{
				value = new Sample
				{
					Remaining = remainingTime,
					Since = time
				};
				Samples[component] = value;
			}
			bool flag2 = val2.IsAlerted();
			float num = remainingTime / Speed(component, ((Component)animal).transform.position);
			if (!flag && !flag2)
			{
				num -= Mathf.Min(time - value.Since, 3f);
			}
			string text = GcLoc.Get("gcs_tame_in", new object[1] { Clock(num) });
			if (flag || flag2)
			{
				text = text + " (" + Localization.instance.Localize(flag2 ? "$hud_tamefrightened" : "$hud_tamehungry") + ")";
			}
			return text;
		}

		private static string? LevelUp(Player local, Character animal)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = animal.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return null;
			}
			ZDO zDO = nview.GetZDO();
			long num = zDO.GetLong(AnimalExperience.LevelUpHash, 0L);
			if (num == 0L)
			{
				return null;
			}
			double totalSeconds = (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds;
			if (totalSeconds < -2.0 || totalSeconds > 4.0)
			{
				return null;
			}
			if (!Celebrated.TryGetValue(zDO.m_uid, out var value) || value != num)
			{
				if (Celebrated.Count > 500)
				{
					Celebrated.Clear();
				}
				Celebrated[zDO.m_uid] = num;
				PlayLevelUp(local, animal);
			}
			return GcLoc.Get("gcs_levelup", new object[1] { Mathf.FloorToInt(zDO.GetFloat(Care.LevelHash, 0f)) });
		}

		private static void PlayLevelUp(Player local, Character animal)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			if (levelUpLocal == null)
			{
				List<EffectData> list = new List<EffectData>();
				EffectData[] effectPrefabs = local.m_skillLevelupEffects.m_effectPrefabs;
				foreach (EffectData val in effectPrefabs)
				{
					if (val != null && (Object)(object)val.m_prefab != (Object)null && (Object)(object)val.m_prefab.GetComponent<ZNetView>() == (Object)null)
					{
						list.Add(val);
					}
				}
				levelUpLocal = new EffectList
				{
					m_effectPrefabs = list.ToArray()
				};
			}
			levelUpLocal.Create(animal.GetTopPoint(), Quaternion.identity, ((Component)animal).transform, 1f, -1, default(ZDOID));
		}

		private static string? Breeding(Character animal)
		{
			ZNetView nview = animal.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || Illusions.IsIllusion(animal))
			{
				return null;
			}
			ZDO zDO = nview.GetZDO();
			DateTime time = ZNet.instance.GetTime();
			Growup component = ((Component)animal).GetComponent<Growup>();
			if ((Object)(object)component != (Object)null)
			{
				long num = zDO.GetLong(ZDOVars.s_spawnTime, 0L);
				if (num == 0L)
				{
					return null;
				}
				return GcLoc.Get("gcs_grown_in", new object[1] { Clock(component.m_growTime - (float)(time - new DateTime(num)).TotalSeconds) });
			}
			Procreation component2 = ((Component)animal).GetComponent<Procreation>();
			long num2 = (((Object)(object)component2 != (Object)null) ? zDO.GetLong(ZDOVars.s_pregnant, 0L) : 0);
			if ((Object)(object)component2 == (Object)null || num2 == 0L)
			{
				return null;
			}
			float seconds = component2.m_pregnancyDuration - (float)(time - new DateTime(num2)).TotalSeconds;
			return GcLoc.Get(((Object)(object)component2.m_offspring != (Object)null && (Object)(object)component2.m_offspring.GetComponent<ItemDrop>() != (Object)null) ? "gcs_egg_in" : "gcs_birth_in", new object[1] { Clock(seconds) });
		}

		private static string? Hatching(ItemDrop item)
		{
			EggGrow component = ((Component)item).GetComponent<EggGrow>();
			if ((Object)(object)component == (Object)null || (Object)(object)item.m_nview == (Object)null || !item.m_nview.IsValid() || item.m_itemData.m_stack > 1)
			{
				return null;
			}
			float num = item.m_nview.GetZDO().GetFloat(ZDOVars.s_growStart, 0f);
			if (!(num > 0f))
			{
				return null;
			}
			return GcLoc.Get("gcs_hatch_in", new object[1] { Clock(num + component.m_growTime - (float)ZNet.instance.GetTimeSeconds()) });
		}

		private static float Speed(Tameable tame, Vector3 position)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			float num = (Care.Enabled.Value ? (1f + 2f * Care.NearbyLevel(position) / 100f) : 1f);
			num *= BondTamingPatch.Factor(position);
			InRange.Clear();
			Player.GetPlayersInRange(position, tame.m_tamingSpeedMultiplierRange, InRange);
			foreach (Player item in InRange)
			{
				if (((Character)item).GetSEMan().HaveStatusAttribute((StatusAttribute)8))
				{
					num *= tame.m_tamingBoostMultiplier;
				}
			}
			return Mathf.Max(0.01f, num);
		}

		private static string Clock(float seconds)
		{
			int num = Mathf.Max(0, Mathf.CeilToInt(seconds));
			return (num / 3600).ToString("00") + ":" + (num / 60 % 60).ToString("00") + ":" + (num % 60).ToString("00");
		}
	}
	internal static class AnimalExperience
	{
		internal static readonly int XpHash = StringExtensionMethods.GetStableHashCode("gc_care_xp");

		internal static readonly int LevelUpHash = StringExtensionMethods.GetStableHashCode("gc_care_levelup");

		private const string Rpc = "GC_AnimalXP";

		private static readonly Dictionary<Character, int> ValidHits = new Dictionary<Character, int>();

		internal static bool On
		{
			get
			{
				if (Care.Enabled.Value)
				{
					return Care.AnimalXp.Value;
				}
				return false;
			}
		}

		internal static void RegisterRpc()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.Register<ZDOID, float>("GC_AnimalXP", (Action<long, ZDOID, float>)RPC_Xp);
			}
		}

		internal static float Requirement(float level)
		{
			return Mathf.Pow(Mathf.Floor(level + 1f), 1.5f) * 0.5f + 0.5f;
		}

		private static float MaxEvent()
		{
			return Mathf.Max(2f, Care.AnimalKillXp.Value * 11f);
		}

		internal static void NoteHit(Character attacker, Character victim)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (!victim.IsPlayer() && !victim.IsTamed() && (int)victim.GetFaction() != 12 && !victim.m_aiSkipTarget)
			{
				if (ValidHits.Count > 256)
				{
					ValidHits.Clear();
				}
				ValidHits[attacker] = Time.frameCount;
			}
		}

		internal static bool TakeHit(Character attacker)
		{
			if (!ValidHits.TryGetValue(attacker, out var value))
			{
				return false;
			}
			ValidHits.Remove(attacker);
			return Time.frameCount - value <= 1;
		}

		internal static void Give(Character? attacker, float amount, bool forwarded = false)
		{
			if (!On || (Object)(object)attacker == (Object)null || !(amount > 0f) || attacker.IsPlayer() || (Object)(object)attacker.m_nview == (Object)null || !attacker.m_nview.IsValid())
			{
				return;
			}
			if (!attacker.m_nview.IsOwner())
			{
				if (!forwarded)
				{
					Send(attacker.m_nview.GetZDO(), amount);
				}
				return;
			}
			Character val = (Illusions.IsIllusion(attacker) ? Illusions.RealOf(attacker) : attacker);
			if ((Object)(object)val == (Object)null || val.IsPlayer() || !val.IsTamed() || val.IsDead() || Care.Summoned(val) || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid())
			{
				return;
			}
			if (!val.m_nview.IsOwner())
			{
				if (!forwarded || (Object)(object)val != (Object)(object)attacker)
				{
					Send(val.m_nview.GetZDO(), amount);
				}
			}
			else
			{
				Add(val.m_nview.GetZDO(), amount);
			}
		}

		private static void Send(ZDO zdo, float amount)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			long owner = zdo.GetOwner();
			if (owner != 0L && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(owner, "GC_AnimalXP", new object[2] { zdo.m_uid, amount });
			}
		}

		private static void RPC_Xp(long sender, ZDOID id, float amount)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(id) : null);
			Character val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Character>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				Give(val2, Mathf.Clamp(amount, 0f, MaxEvent()), forwarded: true);
			}
		}

		private static void Add(ZDO zdo, float amount)
		{
			float num = zdo.GetFloat(Care.LevelHash, 0f);
			float num2 = SpeciesLink.MaxLevel(zdo.GetPrefab());
			if (!(num >= num2) && !((Object)(object)ZNet.instance == (Object)null))
			{
				float num3 = zdo.GetFloat(XpHash, 0f) + amount * Care.AnimalXpFactor.Value * Game.m_skillGainRate;
				if (num3 < Requirement(num))
				{
					zdo.Set(XpHash, num3);
					return;
				}
				zdo.Set(Care.LevelHash, Mathf.Min(num + 1f, num2));
				zdo.Set(XpHash, 0f);
				zdo.Set(LevelUpHash, ZNet.instance.GetTime().Ticks);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "RaiseSkill")]
	internal static class AnimalXpHitPatch
	{
		private static void Postfix(Character __instance)
		{
			if (!__instance.IsPlayer() && __instance.IsTamed() && AnimalExperience.TakeHit(__instance))
			{
				AnimalExperience.Give(__instance, 1f);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class AnimalXpDamagePatch
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			if (AnimalExperience.On && hit != null && !((ZDOID)(ref hit.m_attacker)).IsNone())
			{
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null && (Object)(object)attacker != (Object)(object)__instance && !attacker.IsPlayer() && attacker.IsTamed())
				{
					AnimalExperience.NoteHit(attacker, __instance);
				}
			}
		}
	}
	internal sealed class Tier
	{
		public int Level;

		public int Rank;

		public string Material = "";

		public int Amount;

		public string Bar = "";

		public int BarAmount;

		public int Station;

		public float MinLength;

		public float MaxLength;

		public Color Color;

		public ItemDrop? Prefab;

		public CustomItem? Item;

		private int prefabHash;

		public string PrefabName => "GC_Leash_" + Material;

		public int PrefabHash
		{
			get
			{
				if (prefabHash == 0)
				{
					return prefabHash = StringExtensionMethods.GetStableHashCode(PrefabName);
				}
				return prefabHash;
			}
		}
	}
	internal static class Plugin
	{
		internal const string KeyHolder = "gc_leash_holder";

		internal const string KeyTier = "gc_leash_tier";

		internal const string KeyItemId = "gc_leash_id";

		internal static readonly int HolderHash = StringExtensionMethods.GetStableHashCode("gc_leash_holder");

		internal static readonly int TierHash = StringExtensionMethods.GetStableHashCode("gc_leash_tier");

		internal static readonly int TiedHash = StringExtensionMethods.GetStableHashCode("gc_leash_tied");

		internal static readonly int PostHash = StringExtensionMethods.GetStableHashCode("gc_leash_post");

		internal static readonly int DurabilityHash = StringExtensionMethods.GetStableHashCode("gc_leash_dura");

		internal static readonly int LeashIdHash = StringExtensionMethods.GetStableHashCode("gc_leash_lid");

		internal static readonly int EscapedHash = StringExtensionMethods.GetStableHashCode("gc_leash_escaped");

		internal static readonly int BonusHash = StringExtensionMethods.GetStableHashCode("gc_leash_bonus");

		internal static ManualLogSource Log = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<float> SlipDistance = null;

		internal static ConfigEntry<float> CheckInterval = null;

		internal static ConfigEntry<int> DurabilityStep = null;

		internal static ConfigEntry<bool> PortalTravel = null;

		internal static ConfigEntry<float> ChaseDistance = null;

		internal static ConfigEntry<int> CommandMinLevel = null;

		internal static ConfigEntry<float> CommandCooldown = null;

		internal static ConfigEntry<float> IllusionCooldown = null;

		internal static ConfigEntry<string> AnimalRules = null;

		internal static ConfigEntry<string> PostPieces = null;

		internal static ConfigEntry<bool> WhistlesEnabled = null;

		internal const float IllusionFollowLength = 2f;

		internal static readonly Tier[] Tiers = new Tier[7]
		{
			new Tier
			{
				Level = 2,
				Rank = 1,
				Material = "DeerHide",
				Amount = 5,
				Station = 1,
				MinLength = 2f,
				MaxLength = 5f,
				Color = new Color(0.72f, 0.54f, 0.34f)
			},
			new Tier
			{
				Level = 3,
				Rank = 2,
				Material = "TrollHide",
				Amount = 4,
				Station = 2,
				MinLength = 3.2f,
				MaxLength = 7.25f,
				Color = new Color(0.4f, 0.5f, 0.62f)
			},
			new Tier
			{
				Level = 5,
				Rank = 3,
				Material = "WolfPelt",
				Amount = 4,
				Bar = "Iron",
				BarAmount = 2,
				Station = 3,
				MinLength = 4.5f,
				MaxLength = 9.5f,
				Color = new Color(0.86f, 0.86f, 0.9f)
			},
			new Tier
			{
				Level = 6,
				Rank = 4,
				Material = "LoxPelt",
				Amount = 3,
				Bar = "BlackMetal",
				BarAmount = 2,
				Station = 3,
				MinLength = 5.7f,
				MaxLength = 11.75f,
				Color = new Color(0.64f, 0.5f, 0.32f)
			},
			new Tier
			{
				Level = 7,
				Rank = 5,
				Material = "ScaleHide",
				Amount = 4,
				Bar = "BlackMetal",
				BarAmount = 2,
				Station = 4,
				MinLength = 6.9f,
				MaxLength = 14f,
				Color = new Color(0.45f, 0.64f, 0.56f)
			},
			new Tier
			{
				Level = 8,
				Rank = 6,
				Material = "AskHide",
				Amount = 4,
				Bar = "FlametalNew",
				BarAmount = 2,
				Station = 4,
				MinLength = 8.2f,
				MaxLength = 16.25f,
				Color = new Color(0.66f, 0.3f, 0.24f)
			},
			new Tier
			{
				Level = 10,
				Rank = 7,
				Material = "MooseHide",
				Amount = 4,
				Bar = "Gold",
				BarAmount = 2,
				Station = 4,
				MinLength = 9.4f,
				MaxLength = 18.5f,
				Color = new Color(0.5f, 0.38f, 0.26f)
			}
		};

		private static readonly Dictionary<int, int> RetiredLevels = new Dictionary<int, int>
		{
			[1] = 2,
			[4] = 3,
			[9] = 10
		};

		internal static readonly Dictionary<string, string> RetiredPrefabs = new Dictionary<string, string>
		{
			["GC_Leash_LeatherScraps"] = "GC_Leash_DeerHide",
			["GC_Leash_BjornHide"] = "GC_Leash_TrollHide",
			["GC_Leash_SealHide"] = "GC_Leash_MooseHide"
		};

		internal const float MinLengthPerQuality = 0.2f;

		internal const float MaxLengthPerQuality = 0.5f;

		internal const float FreePart = 0.9f;

		internal const float StretchPart = 1.15f;

		internal const string KeyLength = "gc_leash_len";

		internal const float ShortestLength = 1f;

		internal const float LengthStep = 0.5f;

		internal const float LongestMaxLength = 20f;

		internal static readonly int MinLengthHash = StringExtensionMethods.GetStableHashCode("gc_leash_min");

		internal static readonly int MaxLengthHash = StringExtensionMethods.GetStableHashCode("gc_leash_max");

		private static readonly Dictionary<string, Tier> ByItemName = new Dictionary<string, Tier>();

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

		internal const int MaxQuality = 4;

		internal const int MaxWorkbenchLevel = 5;

		internal static bool On => Enabled.Value;

		internal static float KnotCheckRadius => DragFrom(20f) + 2f;

		internal static float FreeUntil(float maxLength)
		{
			return maxLength * 0.9f;
		}

		internal static float DragFrom(float maxLength)
		{
			return maxLength * 1.15f;
		}

		internal static float MinLength(Tier tier, int quality)
		{
			return tier.MinLength + 0.2f * (float)(ClampQuality(quality) - 1);
		}

		internal static float MaxLength(Tier tier, int quality)
		{
			return Mathf.Max(MinLength(tier, quality) + 1f, tier.MaxLength + 0.5f * (float)(ClampQuality(quality) - 1));
		}

		internal static float SetLength(Tier tier, ItemData? item, int quality)
		{
			float num = MinLength(tier, quality);
			if (item?.m_customData == null || !item.m_customData.TryGetValue("gc_leash_len", out var value) || !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return num;
			}
			return Mathf.Clamp(result, 1f, num);
		}

		internal static float LengthRatio(Tier tier, ItemData? item, int quality)
		{
			return SetLength(tier, item, quality) / MinLength(tier, quality);
		}

		private static float LengthShare(Tier tier, ItemData? item, int quality)
		{
			float num = MinLength(tier, quality);
			if (!(num > 1f))
			{
				return 1f;
			}
			return Mathf.Clamp01((SetLength(tier, item, quality) - 1f) / (num - 1f));
		}

		internal static float WearFactor(Tier tier, ItemData? item, int quality)
		{
			return WearFactorAt(tier, SetLength(tier, item, quality), quality);
		}

		internal static float WearFactorAt(Tier tier, float minLength, int quality)
		{
			float num = MinLength(tier, quality);
			float num2 = ((num > 1f) ? Mathf.Clamp01((minLength - 1f) / (num - 1f)) : 1f);
			return Mathf.Lerp(1.5f, 0.9f, num2);
		}

		internal static float KnotDamageFactor(Tier tier, ItemData? item, int quality)
		{
			return Mathf.Lerp(0.5f, 1f, LengthShare(tier, item, quality));
		}

		private static int ClampQuality(int quality)
		{
			return Mathf.Clamp(quality, 1, 4);
		}

		internal static float LeashBonus(Tier tier, int quality)
		{
			float num = 0.9f / (float)Tiers.Length;
			return 0.1f + num * (float)(Mathf.Clamp(tier.Rank, 1, Tiers.Length) - 1) + num / 3f * (float)(ClampQuality(quality) - 1);
		}

		internal static float SlipFrom(float maxLength)
		{
			return DragFrom(maxLength) + SlipDistance.Value;
		}

		internal static void Init(ConfigFile Config, Harmony harmony)
		{
			Log = ServerPlugin.Log;
			Enabled = Gc.BindSynced<bool>(Config, "7 - Leash", "Enabled", true, "Tierleinen: Leine mit 1–8 in die Hand nehmen, E am gezähmten Tier leint an oder löst, E am Pfosten bindet an; Linksklick schickt das Tier hin, Rechtsklick lässt es angreifen (wird vom Server vorgegeben, auch im Menü GC Option).", (AcceptableValueBase)null);
			SlipDistance = Gc.BindSynced<float>(Config, "7 - Leash", "SlipDistance", 12f, "Sicherung: So viele Meter hinter der Zuggrenze (Höchstlänge + 15 %) rutscht die Leine aus der Hand, das Tier ist frei (wie in Minecraft). Das passiert nur, wenn die Leine das Tier nicht nachziehen kann, etwa über eine tiefe Kante.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f));
			CheckInterval = Gc.BindSynced<float>(Config, "7 - Leash", "CheckInterval", 1f, "Je so viele Sekunden, die die Leine über ihre Höchstlänge gedehnt ist, verliert sie so viel Haltbarkeit, wie das Tier Leinenlast hat (gezählt wird die Zeit, nicht einzelne Stichproben). Kämpfen in Reichweite kostet nichts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f));
			DurabilityStep = Gc.BindSynced<int>(Config, "7 - Leash", "DurabilityPerLeashTier", 30, "Haltbarkeit pro Leinenstufe: Hirschleder 30, Trollleder 60, Wolfspelz 90 … Elchhaut 210 (Jan, 19.10.2026: eine Leine je Biom, die stärkste etwa doppelt so haltbar wie vorher). Löst DurabilityPerTier ab.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100));
			PortalTravel = Gc.BindSynced<bool>(Config, "7 - Leash", "PortalTravel", true, "Angeleinte Tiere kommen bei Teleports mit: durch Portale und in Dungeons (hinein und hinaus).", (AcceptableValueBase)null);
			ChaseDistance = Gc.BindSynced<float>(Config, "7 - Leash", "ChaseDistance", 20f, "Angeleinte Tiere kämpfen, bis der Gegner tot oder weiter als so viele Meter von ihnen weg ist; dann folgen sie wieder dem Spieler.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f));
			CommandMinLevel = Gc.BindSynced<int>(Config, "7 - Leash", "CommandMinLevel", 10, "Befehle mit der Leine in der Hand (Linksklick hinschicken, Rechtsklick angreifen) nimmt ein Tier erst ab dieser Stufe an (Stufe gezüchteter Tiere, Tierpflege; gezähmte Tiere haben Stufe 0). Gilt nur, wenn die Tierpflege an ist.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 150));
			CommandCooldown = Gc.BindSynced<float>(Config, "7 - Leash", "CommandCooldown", 60f, "Pause in Sekunden nach einem Befehl, je Tier. Sie wird um den Durchschnitt aus Tier-Stufe und halber Tierpflege-Stufe des Spielers in Prozent kürzer (Jan, 19.10.2026: Tierpflege zählt halb; 20 und 20: 15 % kürzer; ab 100 %: keine Pause).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f));
			IllusionCooldown = Gc.BindSynced<float>(Config, "7 - Leash", "IllusionCooldown", 300f, "Lokis Blendwerk (EpicLoot): Ein getötetes Trugbild kehrt nach so vielen Sekunden von selbst zurück, solange das Tier an der Leine hängt. Die Zeit läuft in der Leine weiter, auch wenn man neu anleint.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 3600f));
			AnimalRules = Gc.BindSynced<string>(Config, "7 - Leash", "AnimalRules", "", "Eigene Leinenlast (0,5 bis 10, Kommazahl mit Punkt) für Tiere, z. B. aus anderen Mods: Prefab=Leinenlast, durch Komma getrennt, * als Platzhalter. Beispiel: MyBear=2.5, MyMod_*=3. Gilt vor allen eingebauten Regeln und vor Regeln anderer Mods.", (AcceptableValueBase)null);
			PostPieces = Gc.BindSynced<string>(Config, "7 - Leash", "PostPieces", "*pole*, *fence*, *pillar*, *wall*", "Bauteile, an die man Tiere anbinden kann: Pfosten, Zäune, Mauern (Prefab-Namen, durch Komma getrennt, * als Platzhalter). Bauteile mit eigener Benutzen-Funktion (Tore, Fackeln) werden ausgelassen. Gilt für Bauteile, die danach geladen werden.", (AcceptableValueBase)null);
			Enabled.SettingChanged += delegate
			{
				ApplyRecipes();
				Whistles.ApplyRecipes();
			};
			DurabilityStep.SettingChanged += delegate
			{
				ApplyDurability();
			};
			AnimalRules.SettingChanged += delegate
			{
				Ranks.Reload();
			};
			PostPieces.SettingChanged += delegate
			{
				Posts.RulesChanged();
			};
			WhistlesEnabled = Gc.BindSynced<bool>(Config, "7 - Leash", "Whistles", true, "Tierpfeifen (vier: Edelholz an der Werkbank, Eisen, Walkürenpfeife und Flammenmetall an der Schmiede): Linksklick schickt alle Tiere an deinen Leinen hin, Rechtsklick lässt alle angreifen. Bessere Pfeifen verkürzen die Befehlspause (bis −50 %), nach jedem Pfiff ist die Pfeife 5 s gesperrt, jeder Pfiff gibt den gehorchenden Tieren 5 s mehr Tempo (bis +25 %) und ihre Leinen nehmen so lange keinen Schaden; EpicLoot-Verzauberungen der Pfeife wirken dann mit.", (AcceptableValueBase)null);
			WhistlesEnabled.SettingChanged += delegate
			{
				Whistles.ApplyRecipes();
			};
			Ranks.Reload();
			AddLocalization();
			PrefabManager.OnVanillaPrefabsAvailable += CreateItems;
			PrefabManager.OnPrefabsRegistered += Young.AddTameable;
			PrefabManager.OnPrefabsRegistered += Ranks.LogTameable;
			LeashMagic.Init(harmony);
		}

		internal static void Update()
		{
			if (!Gc.IsHeadless)
			{
				Guard("Leinenlänge", Control.TickWheel);
				Guard("Leinen", Links.Tick);
				Guard("Tierpflege", Care.Tick);
				Guard("Countdown", Countdown.Tick);
				Guard("Trugbilder", Illusions.Tick);
				Guard("Verzauberungen", Bonds.Tick);
				Guard("Anzeigen", Bonds.TickVisuals);
				Guard("Ohnmacht", Bonds.TickFaint);
				Guard("Seile", Rope.Tick);
				Guard("Menü", LeashMenu.Update);
				Guard("Leinenleiste", LeashBar.Tick);
				Guard("Aufräumen", Bonds.Cleanup);
				Guard("Verhalten", Behaviour.Cleanup);
			}
		}

		private static void Guard(string part, Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				if (ReportedErrors.Add(part))
				{
					Log.LogWarning((object)$"Tierleinen ({part}): {arg}");
				}
			}
		}

		internal static int MaxDurability(Tier tier)
		{
			return tier.Rank * Math.Max(1, DurabilityStep.Value);
		}

		internal static float DurabilityPerQuality(Tier tier)
		{
			return (float)MaxDurability(tier) * 0.5f;
		}

		internal static int MaterialPerQuality(Tier tier)
		{
			return Math.Max(1, (tier.Amount + 1) / 2);
		}

		internal static bool IsLeash(ItemData? item, out Tier tier)
		{
			tier = null;
			if (item?.m_shared != null)
			{
				return ByItemName.TryGetValue(item.m_shared.m_name, out tier);
			}
			return false;
		}

		internal static Tier? TierAt(int level)
		{
			if (RetiredLevels.TryGetValue(level, out var value))
			{
				level = value;
			}
			Tier[] tiers = Tiers;
			foreach (Tier tier in tiers)
			{
				if (tier.Level == level)
				{
					return tier;
				}
			}
			return null;
		}

		internal static Player? FindPlayer(long playerId)
		{
			if (playerId == 0L)
			{
				return null;
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == playerId)
				{
					return allPlayer;
				}
			}
			return null;
		}

		private static void AddLocalization()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			foreach (string item in new string[7] { "gc_leash_item", "gc_leash_desc", "gc_leash_knot", "gc_leash_knot_desc", "gc_whistle_item", "gc_whistle_desc", "gc_whistle_valkyrie" }.Concat(LeashMagic.LocalizationKeys()))
			{
				string current = item;
				foreach (KeyValuePair<string, string> item2 in GcLoc.AllLanguages(current))
				{
					string key = item2.Key;
					localization.AddTranslation(ref key, ref current, item2.Value);
				}
			}
		}

		private static void CreateItems()
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreateItems;
			try
			{
				Posts.CreateKnotPrefab();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Tierleinen: Knoten-Bauteil nicht erstellt, Anbinden ist aus: " + ex.Message));
			}
			int num = 0;
			Tier[] tiers = Tiers;
			foreach (Tier tier in tiers)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(tier.Material);
				ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					Log.LogInfo((object)$"Leine Stufe {tier.Rank}: Material {tier.Material} gibt es im Spiel nicht, Stufe entfällt.");
					continue;
				}
				if (tier.Bar.Length > 0 && (Object)(object)PrefabManager.Instance.GetPrefab(tier.Bar) == (Object)null)
				{
					Log.LogInfo((object)$"Leine Stufe {tier.Rank}: Barren {tier.Bar} gibt es im Spiel nicht, Stufe entfällt.");
					continue;
				}
				string text = "$gc_leash_item (" + val.m_itemData.m_shared.m_name + ")";
				List<RequirementConfig> list = new List<RequirementConfig>
				{
					new RequirementConfig(tier.Material, tier.Amount, MaterialPerQuality(tier), true)
				};
				if (tier.Bar.Length > 0)
				{
					list.Add(new RequirementConfig(tier.Bar, tier.BarAmount, 1, true));
				}
				ItemConfig val2 = new ItemConfig();
				val2.Name = text;
				val2.Description = "$gc_leash_desc";
				val2.CraftingStation = CraftingStations.Workbench;
				val2.RepairStation = CraftingStations.Workbench;
				val2.MinStationLevel = tier.Station;
				val2.Weight = 0.5f;
				val2.Icons = (Sprite[])(object)new Sprite[1] { LeashIcon.Create(tier.Color) };
				val2.Requirements = list.ToArray();
				ItemConfig val3 = val2;
				val3.StackSize = 1;
				CustomItem val4 = new CustomItem(tier.PrefabName, tier.Material, val3);
				SharedData shared = val4.ItemDrop.m_itemData.m_shared;
				shared.m_name = text;
				try
				{
					Sprite val5 = RopeLook.DressLeash(((Component)val4.ItemDrop).gameObject, tier);
					if ((Object)(object)val5 != (Object)null)
					{
						shared.m_icons = (Sprite[])(object)new Sprite[1] { val5 };
					}
				}
				catch (Exception ex2)
				{
					Log.LogWarning((object)$"Leine Stufe {tier.Rank}: Seilrolle nicht angelegt, es bleibt das alte Aussehen: {ex2.Message}");
				}
				Control.MakeHandItem(((Component)val4.ItemDrop).gameObject, shared, tier);
				shared.m_maxStackSize = 1;
				shared.m_useDurability = true;
				shared.m_canBeReparied = true;
				shared.m_maxQuality = 4;
				shared.m_durabilityPerLevel = DurabilityPerQuality(tier);
				shared.m_maxDurability = MaxDurability(tier);
				shared.m_teleportable = true;
				shared.m_value = 0;
				val4.ItemDrop.m_itemData.m_durability = shared.m_maxDurability;
				if (!ItemManager.Instance.AddItem(val4))
				{
					Log.LogWarning((object)$"Leine Stufe {tier.Rank} ({tier.PrefabName}) konnte nicht registriert werden.");
					continue;
				}
				tier.Prefab = val4.ItemDrop;
				tier.Item = val4;
				ByItemName[text] = tier;
				num++;
			}
			ApplyRecipes();
			Log.LogInfo((object)$"Tierleinen: {num} Stufen erstellt (Haltbarkeit {DurabilityStep.Value} pro Stufe).");
			LeashMagic.RegisterLoot();
			try
			{
				Whistles.CreateItems();
			}
			catch (Exception arg)
			{
				Log.LogWarning((object)$"Tierpfeifen nicht erstellt: {arg}");
			}
		}

		private static void ApplyRecipes()
		{
			Tier[] tiers = Tiers;
			foreach (Tier tier in tiers)
			{
				CustomItem? item = tier.Item;
				object obj;
				if (item == null)
				{
					obj = null;
				}
				else
				{
					CustomRecipe recipe = item.Recipe;
					obj = ((recipe != null) ? recipe.Recipe : null);
				}
				if ((Object)obj != (Object)null)
				{
					tier.Item.Recipe.Recipe.m_enabled = On;
				}
			}
		}

		private static void ApplyDurability()
		{
			Tier[] tiers = Tiers;
			foreach (Tier tier in tiers)
			{
				if (!((Object)(object)tier.Prefab == (Object)null))
				{
					SharedData shared = tier.Prefab.m_itemData.m_shared;
					shared.m_maxDurability = MaxDurability(tier);
					shared.m_durabilityPerLevel = DurabilityPerQuality(tier);
					tier.Prefab.m_itemData.m_durability = shared.m_maxDurability;
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			List<ItemData> list = new List<ItemData>(((Humanoid)localPlayer).GetInventory().GetAllItems());
			Inventory val = LeashBar.Of(localPlayer);
			if (val != null)
			{
				list.AddRange(val.GetAllItems());
			}
			foreach (ItemData item in list)
			{
				if (IsLeash(item, out Tier _))
				{
					item.m_durability = Mathf.Min(item.m_durability, item.GetMaxDurability());
				}
			}
		}
	}
	internal static class Ranks
	{
		internal const float Min = 0.5f;

		internal const float Max = 10f;

		internal const float Step = 0.5f;

		private static readonly Dictionary<string, float> Vanilla = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase)
		{
			["Hen"] = 0.5f,
			["Boar"] = 1f,
			["Wolf"] = 1.5f,
			["Asksvin"] = 2.5f,
			["Moose"] = 3f,
			["Lox"] = 3.5f,
			["Chicken"] = 0.5f,
			["Boar_piggy"] = 0.5f,
			["Wolf_cub"] = 1f,
			["Asksvin_hatchling"] = 1.5f,
			["Moose_calf"] = 1.5f,
			["Lox_Calf"] = 2f,
			["Neck"] = 0.5f,
			["Hare"] = 0.5f,
			["Deer"] = 1.5f,
			["Seal"] = 2f,
			["Bjorn"] = 3f,
			["Unbjorn"] = 3.5f,
			["GC_Bjorn_Cub"] = 1.5f,
			["Boar_spiritcaller"] = 1f,
			["Wolf_spiritcaller"] = 1.5f,
			["Moose_spiritcaller"] = 3f,
			["Bjorn_spiritcaller"] = 2.5f,
			["Skeleton_Friendly"] = 1f
		};

		private static readonly List<KeyValuePair<string, float>> ConfigRules = new List<KeyValuePair<string, float>>();

		internal static readonly List<KeyValuePair<string, float>> ApiRules = new List<KeyValuePair<string, float>>();

		internal static readonly List<Func<GameObject, float>> ApiProviders = new List<Func<GameObject, float>>();

		private static readonly Dictionary<string, float> Cache = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		private static bool logged;

		internal static string Text(float load)
		{
			return load.ToString("0.#");
		}

		private static float Round(float load)
		{
			return Mathf.Max(0.5f, Mathf.Floor(load / 0.5f + 0.5f) * 0.5f);
		}

		internal static void Reload()
		{
			ConfigRules.Clear();
			string[] array = Plugin.AnimalRules.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				int num = text.IndexOfAny(new char[2] { '=', ':' });
				if (num <= 0 || !float.TryParse(text.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					if (text.Length > 0)
					{
						Plugin.Log.LogWarning((object)("Tierleinen: Regel „" + text + "\" nicht verstanden (Prefab=Leinenlast, z. B. MyBear=2.5)."));
					}
				}
				else
				{
					ConfigRules.Add(new KeyValuePair<string, float>(text.Substring(0, num).Trim(), Mathf.Clamp(result, 0.5f, 10f)));
				}
			}
			Cache.Clear();
		}

		internal static void Changed()
		{
			Cache.Clear();
		}

		public static float Of(Character animal)
		{
			return Of(((Component)animal).gameObject);
		}

		public static float Of(GameObject go)
		{
			string text = PrefabName(go);
			if (Cache.TryGetValue(text, out var value))
			{
				return value;
			}
			value = Mathf.Clamp(Resolve(go, text, 0, out string guessed), 0.5f, 10f);
			Cache[text] = value;
			if (guessed != null)
			{
				Plugin.Log.LogInfo((object)("Tierleinen: " + text + " hat keine feste Leinenlast, geschätzt " + Text(value) + " (" + guessed + "). Festlegen mit AnimalRules, z. B. " + text + "=" + value.ToString("0.#", CultureInfo.InvariantCulture) + "."));
			}
			return value;
		}

		internal static string PrefabName(GameObject go)
		{
			string name = ((Object)go).name;
			int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
			if (num < 0)
			{
				return name;
			}
			return name.Substring(0, num).Trim();
		}

		private static float Resolve(GameObject go, string name, int depth, out string? guessed)
		{
			guessed = null;
			if (Match(ConfigRules, name, out var load) || Match(ApiRules, name, out load))
			{
				return load;
			}
			foreach (Func<GameObject, float> apiProvider in ApiProviders)
			{
				try
				{
					load = apiProvider(go);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Tierleinen: Regel einer anderen Mod für " + name + " fehlgeschlagen: " + ex.Message));
					load = 0f;
				}
				if (load > 0f)
				{
					return load;
				}
			}
			if (Vanilla.TryGetValue(name, out load))
			{
				return load;
			}
			Growup component = go.GetComponent<Growup>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_grownPrefab != (Object)null && depth < 3)
			{
				return Round(0.5f * Resolve(component.m_grownPrefab, PrefabName(component.m_grownPrefab), depth + 1, out guessed));
			}
			for (int num = name.LastIndexOf('_'); num > 0; num = name.LastIndexOf('_', num - 1))
			{
				string text = name.Substring(0, num);
				if (Match(ConfigRules, text, out load) || Match(ApiRules, text, out load) || Vanilla.TryGetValue(text, out load))
				{
					return load;
				}
			}
			return Estimate(go, out guessed);
		}

		private static float Estimate(GameObject go, out string? guessed)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unk

GC_WalkuerenTransport.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Courier;
using GC.Server.Leash;
using GC.Shared;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_WalkuerenTransport")]
[assembly: AssemblyTitle("GC_WalkuerenTransport")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModWalkuerenTransport
{
	[BepInPlugin("gorduan.gc.walkuerentransport", "GC_WalkuerenTransport", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.walkuerentransport");
			Transport.Init(((BaseUnityPlugin)this).Config);
			Module.TakeOverOldSettings();
			GcHooks.CourierOn = () => Transport.On;
			GcHooks.CourierWhistle = Transport.OnWhistle;
			GcHooks.CourierTooltip = Transport.TooltipStatus;
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("courier", (ConfigEntryBase)(object)Transport.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("courier_meat", (ConfigEntryBase)(object)Transport.MeatAmount, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("courier_ymir", (ConfigEntryBase)(object)Transport.YmirAmount, 1.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("courier_raid", (ConfigEntryBase)(object)Transport.RaidAfter, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("courier_easter", (ConfigEntryBase)(object)Transport.EasterEgg, 0.0, "", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null);
		}

		private void Update()
		{
			Module.Guard("Walküren-Transport", (Action)Transport.Tick);
		}
	}
	internal static class GcMod
	{
		public const string Id = "walkuerentransport";

		public const string Guid = "gorduan.gc.walkuerentransport";

		public const string Name = "GC_WalkuerenTransport";

		public const string Version = "1.8.1";

		public const int Stufe = 5;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "walkuerentransport";
				val.Guid = "gorduan.gc.walkuerentransport";
				val.Name = "GC_WalkuerenTransport";
				val.Version = "1.8.1";
				val.Stufe = 5;
				val.Seite = (GcSeite)2;
				val.Braucht = new string[1] { "tiere" };
				val.Partner = Array.Empty<string>();
				val.Fremd = Array.Empty<string>();
				val.AlteConfig = "gorduan.gc_server.cfg";
				val.Ausgleich = 0f;
				return val;
			}
		}
	}
}
namespace GC.Server.Courier
{
	internal static class Easter
	{
		internal const float CallSeconds = 44f;

		internal const string VoidEnv = "GC_CourierVoid";

		internal const string BloodEnv = "GC_CourierBlood";

		internal const string ToxicEnv = "GC_CourierToxic";

		internal const string GoldEnv = "GC_CourierGold";

		private static readonly string[] MixEnvs = new string[13]
		{
			"Misty", "Bonemass", "SnowStorm", "Ashlands_storm", "Mistlands_thunder", "GDKing", "Eikthyr", "GoblinKing", "Crypt", "DeepForest Mist",
			"Darklands_dark", "Twilight_SnowStorm", "Moder"
		};

		private static readonly string[] Fireworks = new string[9] { "vfx_Firework_Rocket_Red", "vfx_Firework_Rocket_Blue", "vfx_Firework_Rocket_Green", "vfx_Firework_Rocket_Yellow", "vfx_Firework_Rocket_Purple", "vfx_Firework_Rocket_Cyan", "vfx_FireWork_ThunderStone", "vfx_FireWork_BlackCore", "vfx_FireWork_SurtlingCore" };

		private static readonly string[] SkyBlasts = new string[4] { "fx_goblinking_meteor_hit", "fx_fader_meteor_hit", "fx_dynamite_explosion", "fx_siegebomb_explosion" };

		private static readonly string[] Fogs = new string[4] { "vfx_ground_fog", "vfx_swamp_mist", "vfx_mistlands_mist", "vfx_darkland_groundfog" };

		private static readonly string[] BossCries = new string[7] { "sfx_dragon_scream", "sfx_gdking_scream", "sfx_Bonemass_alert", "sfx_eikthyr_alert", "fx_goblinking_vo_meteors1", "sfx_frozenking_voice_scream", "sfx_fenring_howl" };

		private static readonly string[] Risers = new string[5] { "vfx_ghost_spawn", "vfx_DraugrSpawn", "fx_summon_skeleton_spawn", "vfx_odin_despawn", "fx_raven_despawn" };

		private static float shakeUntil;

		private static float shakeStrength;

		private static Image? flash;

		internal static IEnumerator Call(Vector3 center, Show.Dummy? cart, bool mine, long playerId)
		{
			//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)
			float start = Time.time;
			Transform cartTransform = (((Object)(object)cart?.Root != (Object)null) ? cart.Root.transform : null);
			Vector3 cartPosition = (((Object)(object)cartTransform != (Object)null) ? cartTransform.position : center);
			Quaternion cartRotation = (((Object)(object)cartTransform != (Object)null) ? cartTransform.rotation : Quaternion.identity);
			CourierRunner runner = Show.Runner();
			((MonoBehaviour)runner).StartCoroutine(Quake(center));
			Coroutine float_ = (((Object)(object)cartTransform != (Object)null) ? ((MonoBehaviour)runner).StartCoroutine(Levitate(cartTransform, cartPosition, cartRotation, start)) : null);
			GameCamera camera = GameCamera.instance;
			float fov = (((Object)(object)camera != (Object)null) ? camera.m_fov : 65f);
			Show.Sky("GC_CourierVoid", 4f, 0.3f);
			Sounds.Play("heartbeat", center, 1f, 200f, global: true);
			Message("gccr_egg_1");
			yield return Until(start, 1.8f);
			Show.Local("sfx_fenring_howl", center + Ring(60f) + Vector3.up * 10f, Quaternion.identity);
			Sounds.Play("heartbeat", center, 1f, 200f, global: true);
			yield return Until(start, 3.5f);
			Show.Local("fx_bossstone_activate_Eikthyr", center, Quaternion.identity);
			Show.Local("fx_Fader_Roar", center + Vector3.up * 20f, Quaternion.identity);
			Show.Music("gc_music_easter", 44f + Show.PickupSeconds(easter: true));
			Sounds.Play("quake_rumble", center, 0.9f, 250f, global: true);
			Shake(4.5f, 3.5f);
			Message("gccr_egg_2");
			for (float t = 3.5f; t < 8f; t += 0.35f)
			{
				Vector3 point = center + Ring(Random.Range(4f, 18f));
				Ground(ref point);
				Show.Local((Random.value < 0.5f) ? "vfx_gdking_stomp" : "fx_eikthyr_stomp", point, Quaternion.identity);
				yield return Until(start, t);
			}
			Show.Sky("GC_CourierBlood", 6.5f, 0.5f);
			Message("gccr_egg_3");
			bool struck = false;
			for (float t = 8f; t < 14f; t += Random.Range(0.18f, 0.45f))
			{
				if (!struck && t >= 9f)
				{
					struck = true;
					Show.Strike(center, mine);
					Show.Local("sfx_thunder", center + Vector3.up * 3f, Quaternion.identity);
					Show.Local("sfx_mistlands_thunder", center + Vector3.up * 10f, Quaternion.identity);
					Flash(new Color(0.75f, 0.85f, 1f), 0.35f);
					if ((Object)(object)cart?.Root != (Object)null)
					{
						((MonoBehaviour)runner).StartCoroutine(Show.BlueFire(cart.Root, 30f, 3.2f));
					}
				}
				Vector3 point2 = center + Ring(Random.Range(7f, 35f));
				Ground(ref point2);
				Show.Local((Random.value < 0.6f) ? "fx_Lightning" : "fx_Lightning_red", point2, Quaternion.identity, Random.Range(0.8f, 1.6f));
				Show.Local("sfx_thunder", point2, Quaternion.identity);
				if (Random.value < 0.25f)
				{
					Flash(Color.white, 0.12f);
				}
				yield return Until(start, t);
			}
			List<(string message, string env)> raids = RaidAnnouncements();
			for (int i = 0; i < 6; i++)
			{
				float num = 14f + (float)i * 1.15f;
				string text;
				string text2;
				if (raids.Count > 0)
				{
					(text, text2) = raids[i % raids.Count];
				}
				else
				{
					text = "";
					text2 = "";
				}
				Show.Sky((text2.Length > 0 && (Object)(object)EnvMan.instance != (Object)null && EnvMan.instance.GetEnv(text2) != null) ? text2 : MixEnvs[Random.Range(0, MixEnvs.Length)], 1.4f, 0.35f);
				if (text.Length > 0)
				{
					MessageHud instance = MessageHud.instance;
					if (instance != null)
					{
						instance.ShowMessage((MessageType)2, Localization.instance.Localize(text), 0, (Sprite)null, false, true);
					}
				}
				Vector3 point3 = center + Ring(Random.Range(5f, 20f));
				Ground(ref point3);
				Show.Local(Fogs[i % Fogs.Length], point3, Quaternion.identity, 2f, null, 9f);
				Show.Local(BossCries[i % BossCries.Length], center + Ring(40f) + Vector3.up * 15f, Quaternion.identity);
				if (i == 2)
				{
					Show.Local("sfx_fenring_howl", center + Ring(25f), Quaternion.identity);
				}
				yield return Until(start, num + 1.15f);
			}
			Show.Sky("GC_CourierGold", 8f, 0.6f);
			Message("gccr_egg_4");
			for (float t = 21f; t < 29f; t += 0.3f)
			{
				Vector3 point4 = center + Ring(Random.Range(3f, 25f));
				Ground(ref point4);
				Show.Local(Fireworks[Random.Range(0, Fireworks.Length)], point4, Quaternion.Euler(Random.Range(-8f, 8f), 0f, Random.Range(-8f, 8f)));
				if (Random.value < 0.35f)
				{
					Vector3 position = center + Ring(Random.Range(20f, 70f)) + Vector3.up * Random.Range(45f, 90f);
					Show.Local(SkyBlasts[Random.Range(0, SkyBlasts.Length)], position, Quaternion.identity, Random.Range(2f, 4f));
					Sounds.Play("boom_big", position, 0.8f, 400f);
				}
				if (Random.value < 0.22f)
				{
					((MonoBehaviour)runner).StartCoroutine(Comet(center));
				}
				yield return Until(start, t);
			}
			Show.Sky("GC_CourierToxic", 6.5f, 0.5f);
			Message("gccr_egg_5");
			for (float t = 29f; t < 35f; t += 0.4f)
			{
				Vector3 point5 = center + Ring(Random.Range(6f, 14f));
				Ground(ref point5);
				Show.Local(Risers[Random.Range(0, Risers.Length)], point5, Quaternion.identity, 1.5f);
				if (Random.value < 0.3f)
				{
					Show.Local("sfx_ghost_alert", point5 + Vector3.up * 2f, Quaternion.identity);
				}
				if (t > 31f && t < 31.5f)
				{
					Sounds.Play("scream_wail", center + Ring(15f), 1f, 250f, global: true);
				}
				yield return Until(start, t);
			}
			Message("gccr_egg_6");
			Show.Local("fx_bossstone_activate_Yagluth", center, Quaternion.identity);
			Show.Local("fx_Fader_Roar", center + Vector3.up * 20f, Quaternion.identity);
			Shake(6f, 6f);
			string[] flicker = new string[4] { "GC_CourierVoid", "GC_CourierBlood", "GC_CourierGold", "GC_CourierToxic" };
			int f = 0;
			for (float t = 35f; t < 40.5f; t += 0.15f)
			{
				Show.Sky(flicker[f++ % flicker.Length], 0.6f, 0.1f);
				Vector3 point6 = center + Ring(Random.Range(5f, 30f));
				Ground(ref point6);
				Show.Local("fx_Lightning", point6, Quaternion.identity, 1.3f);
				if (f % 3 == 0)
				{
					Show.Local(Fireworks[Random.Range(0, Fireworks.Length)], point6, Quaternion.identity);
				}
				if (f % 5 == 0)
				{
					Flash(Color.white, 0.1f);
					Show.Local("sfx_thunder", point6, Quaternion.identity);
				}
				if ((Object)(object)camera != (Object)null)
				{
					camera.m_fov = fov + Mathf.Sin((t - 35f) * 3f) * 12f;
				}
				yield return Until(start, t);
			}
			if ((Object)(object)camera != (Object)null)
			{
				camera.m_fov = fov;
			}
			Show.Local("vfx_GodExplosion", center + Vector3.up * 2f, Quaternion.identity);
			Sounds.Play("boom_big", center, 1f, 400f, global: true);
			Flash(Color.white, 0.6f);
			Shake(1.2f, 9f);
			shakeUntil = 0f;
			Show.Sky("Clear", 2f, 0.2f);
			((MonoBehaviour)runner).StartCoroutine(Show.Hush(2.6f));
			if (float_ != null)
			{
				((MonoBehaviour)runner).StopCoroutine(float_);
			}
			if ((Object)(object)cartTransform != (Object)null)
			{
				((MonoBehaviour)runner).StartCoroutine(Settle(cartTransform, cartPosition, cartRotation));
			}
			yield return Until(start, 42f);
			Show.Sky("GDKing", 1800f, 1.5f, center, 250f);
			Show.Music("gc_music_easter", 1800f, center, 250f);
			Show.Local("fx_bossstone_activate_TheElder", center, Quaternion.identity);
			Message("gccr_egg_guards");
			Vector3[] spots = Guards.Spots(center, playerId);
			Vector3[] array = spots;
			foreach (Vector3 position2 in array)
			{
				Show.Local("vfx_prespawn", position2, Quaternion.identity, 2.5f, null, 8f);
				Show.Local("sfx_prespawn", position2, Quaternion.identity);
			}
			yield return Until(start, 47f);
			Shake(2.5f, 4f);
			array = spots;
			foreach (Vector3 position3 in array)
			{
				Show.Local("vfx_spawn_large", position3, Quaternion.identity, 2.5f);
				Show.Local("sfx_gdking_spawn", position3, Quaternion.identity);
				Show.Local("fx_gdking_rootspawn", position3, Quaternion.identity, 1.5f);
			}
			if (mine && (!Show.FinaleAt.TryGetValue(playerId, out var value) || !(value >= start)))
			{
				Player localPlayer = Player.m_localPlayer;
				List<ZDOID> ids = (((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, center) < 120f) ? Guards.Spawn(center, playerId) : new List<ZDOID>());
				Transport.ReportGuards(playerId, ids);
			}
		}

		private static WaitForSeconds? Until(float start, float seconds)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			float num = start + seconds - Time.time;
			if (!(num > 0f))
			{
				return null;
			}
			return new WaitForSeconds(num);
		}

		private static void Message(string key)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, GcLoc.Get(key, Array.Empty<object>()), 0, (Sprite)null, false, true);
			}
		}

		private static Vector3 Ring(float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Vector2 insideUnitCircle = Random.insideUnitCircle;
			Vector2 normalized = ((Vector2)(ref insideUnitCircle)).normalized;
			return new Vector3(normalized.x, 0f, normalized.y) * radius;
		}

		private static void Ground(ref Vector3 point)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			float y = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetSolidHeight(point, ref y, 1000))
			{
				point.y = y;
			}
		}

		private static void Shake(float seconds, float strength)
		{
			shakeUntil = Time.time + seconds;
			shakeStrength = strength;
		}

		private static IEnumerator Quake(Vector3 center)
		{
			//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)
			float end = Time.time + 44f;
			while (Time.time < end)
			{
				if (Time.time < shakeUntil && (Object)(object)GameCamera.instance != (Object)null)
				{
					GameCamera.instance.AddShake(center, 80f, shakeStrength * (0.7f + Mathf.PerlinNoise(Time.time * 3f, 0f) * 0.6f), true);
				}
				yield return null;
			}
		}

		private static IEnumerator Levitate(Transform cart, Vector3 position, Quaternion rotation, float start)
		{
			//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)
			//IL_0015: 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)
			float spin = 0f;
			while ((Object)(object)cart != (Object)null)
			{
				float num = Time.time - start;
				float num2 = ((num < 3.5f) ? 0f : (Mathf.Min(2.2f, (num - 3.5f) * 0.45f) + ((num > 35f) ? Mathf.Min(2f, (num - 35f) * 0.8f) : 0f)));
				float num3 = ((num < 8f) ? 0f : ((num < 35f) ? 25f : 160f));
				spin += num3 * Time.deltaTime;
				Vector3 val = ((num < 3.5f) ? (Random.insideUnitSphere * 0.02f) : (Random.insideUnitSphere * 0.05f));
				cart.position = position + Vector3.up * (num2 + Mathf.Sin(num * 2f) * 0.15f * Mathf.Clamp01(num2)) + val;
				cart.rotation = rotation * Quaternion.Euler(Mathf.Sin(num * 1.3f) * 6f * Mathf.Clamp01(num2), spin, Mathf.Cos(num * 1.7f) * 6f * Mathf.Clamp01(num2));
				yield return null;
			}
		}

		private static IEnumerator Settle(Transform cart, Vector3 position, Quaternion rotation)
		{
			//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)
			//IL_0015: 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)
			if (!((Object)(object)cart == (Object)null))
			{
				Vector3 from = cart.position;
				Quaternion turn = cart.rotation;
				float t = 0f;
				while (t < 1f && (Object)(object)cart != (Object)null)
				{
					t += Time.deltaTime / 0.8f;
					float num = t * t;
					cart.position = Vector3.Lerp(from, position, num);
					cart.rotation = Quaternion.Slerp(turn, rotation, num);
					yield return null;
				}
				if ((Object)(object)cart != (Object)null)
				{
					cart.position = position;
					cart.rotation = rotation;
					Show.Local("sfx_cart_hit", position, Quaternion.identity);
				}
			}
		}

		private static IEnumerator Comet(Vector3 center)
		{
			//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)
			Vector3 from = center + Ring(160f) + Vector3.up * Random.Range(70f, 110f);
			Vector3 to = center - (from - center) * 0.6f + Vector3.up * Random.Range(40f, 70f);
			to.y = Mathf.Max(to.y, center.y + 40f);
			GameObject comet = new GameObject("GC_CourierComet");
			comet.transform.position = from;
			string[] array = new string[3] { "vfx_Burning", "vfx_Burning_blue", "vfx_Burning_green" };
			Show.Local(array[Random.Range(0, array.Length)], from, Quaternion.identity, 4f, comet.transform);
			Light obj = comet.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.range = 40f;
			obj.intensity = 3f;
			obj.color = new Color(1f, 0.6f, 0.25f);
			float seconds = Random.Range(2.2f, 3.5f);
			float t = 0f;
			while (t < seconds && (Object)(object)comet != (Object)null)
			{
				t += Time.deltaTime;
				float num = t / seconds;
				comet.transform.position = Vector3.Lerp(from, to, num) + Vector3.up * Mathf.Sin(num * (float)Math.PI) * 15f;
				yield return null;
			}
			if ((Object)(object)comet != (Object)null)
			{
				Show.Local(SkyBlasts[Random.Range(0, SkyBlasts.Length)], comet.transform.position, Quaternion.identity, 3f);
				Sounds.Play("boom_big", comet.transform.position, 0.7f, 400f);
				Object.Destroy((Object)(object)comet);
			}
		}

		private static List<(string, string)> RaidAnnouncements()
		{
			List<(string, string)> list = new List<(string, string)>();
			if ((Object)(object)RandEventSystem.instance != (Object)null)
			{
				foreach (RandomEvent @event in RandEventSystem.instance.m_events)
				{
					if (@event != null && !string.IsNullOrEmpty(@event.m_startMessage) && @event.m_name != "gc_hen_raid")
					{
						list.Add((@event.m_startMessage, @event.m_forceEnvironment ?? ""));
					}
				}
			}
			for (int num = list.Count - 1; num > 0; num--)
			{
				int num2 = Random.Range(0, num + 1);
				List<(string, string)> list2 = list;
				int index = num;
				List<(string, string)> list3 = list;
				int index2 = num2;
				(string, string) value = list[num2];
				(string, string) value2 = list[num];
				list2[index] = value;
				list3[index2] = value2;
			}
			return list;
		}

		private static void Flash(Color color, float seconds)
		{
			//IL_00b3: 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_001b: Expected O, but got Unknown
			//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_0084: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)flash == (Object)null)
			{
				GameObject val = new GameObject("GC_CourierFlash");
				val.transform.SetParent(((Component)Show.Runner()).transform, false);
				Canvas obj = val.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 30000;
				GameObject val2 = new GameObject("Flash");
				val2.transform.SetParent(val.transform, false);
				flash = val2.AddComponent<Image>();
				((Graphic)flash).raycastTarget = false;
				RectTransform rectTransform = ((Graphic)flash).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
			}
			((MonoBehaviour)Show.Runner()).StartCoroutine(FadeFlash(color, seconds));
		}

		private static IEnumerator FadeFlash(Color color, float seconds)
		{
			//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)
			float t = 0f;
			while (t < seconds && (Object)(object)flash != (Object)null)
			{
				t += Time.deltaTime;
				Color color2 = color;
				color2.a = Mathf.Lerp(0.85f, 0f, t / seconds);
				((Graphic)flash).color = color2;
				yield return null;
			}
			if ((Object)(object)flash != (Object)null)
			{
				((Graphic)flash).color = Color.clear;
			}
		}
	}
	internal static class Guards
	{
		internal static readonly string[] Prefabs = new string[3] { "Greydwarf", "Greydwarf_Elite", "Greydwarf_Shaman" };

		internal const int Level = 3;

		internal const float HealthFactor = 2f;

		internal const float DamageFactor = 2f;

		internal const float Scale = 2.6f;

		internal const float Distance = 12f;

		internal static readonly int MarkHash = StringExtensionMethods.GetStableHashCode("gc_courier_guard");

		internal static readonly int RagdollScaleHash = StringExtensionMethods.GetStableHashCode("gc_courier_guard_ragdoll");

		internal static Vector3[] Spots(Vector3 center, long playerId)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Abs((float)(playerId % 360));
			Vector3[] array = (Vector3[])(object)new Vector3[Prefabs.Length];
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = (num + (float)i * 120f) * ((float)Math.PI / 180f);
				Vector3 val = center + new Vector3(Mathf.Sin(num2), 0f, Mathf.Cos(num2)) * 12f;
				if ((Object)(object)ZoneSystem.instance != (Object)null)
				{
					val.y = ZoneSystem.instance.GetGroundHeight(val);
				}
				array[i] = val;
			}
			return array;
		}

		internal static List<ZDOID> Spawn(Vector3 center, long playerId)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			List<ZDOID> list = new List<ZDOID>();
			Vector3[] array = Spots(center, playerId);
			for (int i = 0; i < Prefabs.Length; i++)
			{
				GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(Prefabs[i]) : null);
				if ((Object)(object)val == (Object)null)
				{
					ServerPlugin.Log.LogWarning((object)("Walküren-Transport: Wächter " + Prefabs[i] + " fehlt."));
					continue;
				}
				Vector3 val2 = center - array[i];
				val2.y = 0f;
				GameObject val3 = Object.Instantiate<GameObject>(val, array[i] + Vector3.up * 0.5f, (((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val2) : Quaternion.identity);
				Character component = val3.GetComponent<Character>();
				ZNetView component2 = val3.GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsValid())
				{
					Object.Destroy((Object)(object)val3);
					continue;
				}
				component2.GetZDO().Set(MarkHash, true);
				component2.GetZDO().Set(ZDOVars.s_bossCount, true);
				component.SetLevel(3);
				component.SetHealth(component.GetMaxHealth());
				Apply(component);
				BaseAI baseAI = component.GetBaseAI();
				MonsterAI val4 = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
				if (val4 != null)
				{
					val4.SetDespawnInDay(false);
					((BaseAI)val4).SetHuntPlayer(true);
					((BaseAI)val4).Alert();
				}
				list.Add(component2.GetZDO().m_uid);
			}
			ServerPlugin.Log.LogInfo((object)$"Walküren-Transport: {list.Count} Wächter erschienen.");
			return list;
		}

		internal static bool Is(Character? character)
		{
			ZNetView val = (((Object)(object)character != (Object)null) ? character.m_nview : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return val.GetZDO().GetBool(MarkHash, false);
			}
			return false;
		}

		internal static void Apply(Character character)
		{
			//IL_0007: 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)
			Transform transform = ((Component)character).transform;
			transform.localScale *= 2.6f;
			character.m_boss = true;
			character.m_dontHideBossHud = true;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class GuardAwakePatch
	{
		private static void Postfix(Character __instance)
		{
			try
			{
				if (Guards.Is(__instance))
				{
					Guards.Apply(__instance);
				}
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Walküren-Transport: Wächter nicht eingerichtet: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Character), "SetupMaxHealth")]
	internal static class GuardHealthPatch
	{
		private static bool Prefix(Character __instance)
		{
			if (!Guards.Is(__instance))
			{
				return true;
			}
			__instance.SetMaxHealth(__instance.GetMaxHealthBase() * (float)__instance.GetLevel() * 2f);
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	internal static class GuardDeathPatch
	{
		private static void Prefix(Character __instance)
		{
			if (Guards.Is(__instance))
			{
				__instance.m_nview.GetZDO().Set(ZDOVars.s_bossCount, false);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "OnRagdollCreated")]
	internal static class GuardRagdollPatch
	{
		private static void Postfix(Humanoid __instance, Ragdoll ragdoll)
		{
			//IL_001a: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ragdoll == (Object)null) && Guards.Is((Character?)(object)__instance))
			{
				Transform transform = ((Component)ragdoll).transform;
				if (transform.localScale.x < ((Component)__instance).transform.localScale.x * 0.9f)
				{
					transform.localScale *= 2.6f;
				}
				ZNetView component = ((Component)ragdoll).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					component.GetZDO().Set(Guards.RagdollScaleHash, transform.localScale.x);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Awake")]
	internal static class GuardRagdollAwakePatch
	{
		private static void Postfix(Ragdoll __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				float num = component.GetZDO().GetFloat(Guards.RagdollScaleHash, 0f);
				if (num > 0f)
				{
					((Component)__instance).transform.localScale = Vector3.one * num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
	internal static class GuardHudPatch
	{
		private static readonly List<HudData> Bosses = new List<HudData>();

		private static bool shifted;

		private static void Postfix(EnemyHud __instance)
		{
			//IL_00c0: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: 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_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)
			Bosses.Clear();
			bool flag = false;
			foreach (HudData value in __instance.m_huds.Values)
			{
				if ((Object)(object)value.m_gui != (Object)null && (Object)(object)value.m_character != (Object)null && value.m_character.IsBoss())
				{
					Bosses.Add(value);
					flag |= Guards.Is(value.m_character);
				}
			}
			if (!flag && !shifted)
			{
				return;
			}
			RectTransform val = (RectTransform)(((Object)(object)__instance.m_baseHudBoss != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Rect rect = val.rect;
			float num;
			if (!(((Rect)(ref rect)).height > 10f))
			{
				num = 60f;
			}
			else
			{
				rect = val.rect;
				num = Mathf.Min(((Rect)(ref rect)).height, 120f) + 8f;
			}
			float num2 = num;
			Bosses.Sort((HudData a, HudData b) => ((Object)a.m_character).GetInstanceID().CompareTo(((Object)b.m_character).GetInstanceID()));
			for (int num3 = 0; num3 < Bosses.Count; num3++)
			{
				Transform transform = Bosses[num3].m_gui.transform;
				RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val2 != null)
				{
					val2.anchoredPosition = val.anchoredPosition + Vector2.down * (flag ? (num2 * (float)num3) : 0f);
				}
			}
			shifted = flag;
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class GuardDamagePatch
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			if (hit != null)
			{
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null && (Object)(object)attacker != (Object)(object)__instance && Guards.Is(attacker))
				{
					hit.ApplyModifier(2f);
				}
			}
		}
	}
	internal static class Raids
	{
		private sealed class Pending
		{
			public Vector3 Position;

			public bool Easter;

			public double Since;

			public ZDOID Cargo;
		}

		private sealed class Running
		{
			public string Name = "";

			public Vector3 Position;

			public ZDOID Cargo;
		}

		private const float PlayerRange = 96f;

		private static readonly List<Pending> Queue = new List<Pending>();

		private static readonly List<Running> Active = new List<Running>();

		private static double nextCheck;

		internal static void Reset()
		{
			Queue.Clear();
			Active.Clear();
			nextCheck = 0.0;
		}

		internal static void After(Vector3 position, bool easter, ZDOID cargo)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Queue.Add(new Pending
			{
				Position = position,
				Easter = easter,
				Since = Transport.Now,
				Cargo = cargo
			});
		}

		internal static void ServerTick(double now)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			if ((Queue.Count == 0 && Active.Count == 0) || now < nextCheck)
			{
				return;
			}
			nextCheck = now + 2.0;
			RandEventSystem instance = RandEventSystem.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			RandomEvent currentRandomEvent = instance.GetCurrentRandomEvent();
			Running[] array = Active.ToArray();
			foreach (Running running in array)
			{
				if (currentRandomEvent == null || currentRandomEvent.m_name != running.Name || Utils.DistanceXZ(currentRandomEvent.m_pos, running.Position) > 1f)
				{
					Active.Remove(running);
					Transport.Unlock(running.Cargo, raidOver: true);
				}
			}
			if (Queue.Count == 0)
			{
				return;
			}
			Pending pending = Queue[0];
			if (now - pending.Since > 600.0)
			{
				Queue.RemoveAt(0);
				ServerPlugin.Log.LogInfo((object)"Walküren-Transport: Raid nach dem Abholen entfällt, es lief zu lange ein anderer.");
				Transport.Unlock(pending.Cargo, raidOver: false);
			}
			else if (instance.GetCurrentRandomEvent() == null)
			{
				Queue.RemoveAt(0);
				bool flag = false;
				try
				{
					flag = Start(instance, pending);
				}
				catch (Exception arg)
				{
					ServerPlugin.Log.LogWarning((object)$"Walküren-Transport: Raid nicht gestartet: {arg}");
				}
				if (!flag)
				{
					Transport.Unlock(pending.Cargo, raidOver: false);
				}
			}
		}

		private static bool Start(RandEventSystem events, Pending raid)
		{
			//IL_0001: 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_0092: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (!AnyPlayerNear(raid.Position))
			{
				ServerPlugin.Log.LogInfo((object)"Walküren-Transport: Raid nach dem Abholen entfällt, niemand ist mehr am Karren.");
				return false;
			}
			if (Game.m_eventRate <= 0f)
			{
				ServerPlugin.Log.LogInfo((object)"Walküren-Transport: kein Raid, die Welt-Einstellung schaltet Raids aus.");
				return false;
			}
			RandomEvent val = (RandomEvent)(raid.Easter ? ((object)events.GetEvent("gc_hen_raid")) : ((object)Choose(events, raid.Position)));
			if (val == null)
			{
				ServerPlugin.Log.LogInfo((object)("Walküren-Transport: kein Raid möglich (" + (raid.Easter ? "Kampfhühner fehlen" : "Weltstand, Einstellungen") + ")."));
				return false;
			}
			events.SetRandomEvent(val, raid.Position);
			RandomEvent currentRandomEvent = events.GetCurrentRandomEvent();
			if (currentRandomEvent != null)
			{
				currentRandomEvent.m_pauseIfNoPlayerInArea = false;
			}
			Transport.AnnounceRaid(raid.Position, val.m_name);
			Active.Add(new Running
			{
				Name = val.m_name,
				Position = raid.Position,
				Cargo = raid.Cargo
			});
			ServerPlugin.Log.LogInfo((object)$"Walküren-Transport: Raid „{val.m_name}“ bei {raid.Position:F0}, der Karren lässt sich danach rufen.");
			return true;
		}

		private static RandomEvent? Choose(RandEventSystem events, Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			RandEventSystem.RefreshPlayerEventData();
			List<PlayerEventData> s_playerEventDatas = RandEventSystem.s_playerEventDatas;
			bool flag = (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)17);
			List<RandomEvent> list = new List<RandomEvent>();
			foreach (RandomEvent ev in events.m_events)
			{
				if (ev != null && ev.m_enabled && !ev.m_devDisabled && ev.m_random && !(ev.m_name == "gc_hen_raid") && events.HaveGlobalKeys(ev, s_playerEventDatas) && (!flag || s_playerEventDatas.Any((PlayerEventData p) => Utils.DistanceXZ(p.position, position) < 150f && p.possibleEvents != null && p.possibleEvents.Contains(ev.m_name))) && events.InValidBiome(ev, position))
				{
					list.Add(ev);
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list[Random.Range(0, list.Count)];
		}

		private static bool AnyPlayerNear(Vector3 position)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer != (Object)null && Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, position) < 96f)
			{
				return true;
			}
			foreach (ZDO allCharacterZDO in ZNet.instance.GetAllCharacterZDOS())
			{
				if (Utils.DistanceXZ(allCharacterZDO.GetPosition(), position) < 96f && allCharacterZDO.GetPosition().y < 3000f)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class RaidHens
	{
		internal const string Prefab = "GC_RaidHen";

		internal const string EventName = "gc_hen_raid";

		private static GameObject? prefab;

		private static readonly Dictionary<int, float> LastCluck = new Dictionary<int, float>();

		private static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("GC_RaidHen");

		internal static void Init()
		{
			PrefabManager.OnVanillaPrefabsAvailable += CreatePrefab;
		}

		private static void CreatePrefab()
		{
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= CreatePrefab;
			try
			{
				GameObject val = PrefabManager.Instance.GetPrefab("Boar");
				GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("GC_RaidHen", "Hen");
				if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null)
				{
					ServerPlugin.Log.LogWarning((object)"Kampfhühner: Henne oder Wildschwein fehlt, der Hühner-Raid entfällt.");
					return;
				}
				Type[] array = new Type[5]
				{
					typeof(Tameable),
					typeof(Procreation),
					typeof(CharacterDrop),
					typeof(Growup),
					typeof(EggGrow)
				};
				foreach (Type type in array)
				{
					Component[] components = val2.GetComponents(type);
					for (int j = 0; j < components.Length; j++)
					{
						Object.DestroyImmediate((Object)(object)components[j]);
					}
				}
				Character component = val.GetComponent<Character>();
				Humanoid component2 = val.GetComponent<Humanoid>();
				MonsterAI component3 = val.GetComponent<MonsterAI>();
				Humanoid val3 = MakeHumanoid(val2);
				MonsterAI component4 = val2.GetComponent<MonsterAI>();
				if ((Object)(object)val3 == (Object)null || (Object)(object)component4 == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
				{
					ServerPlugin.Log.LogWarning((object)"Kampfhühner: Henne lässt sich nicht kampffähig machen, der Hühner-Raid entfällt.");
					Object.DestroyImmediate((Object)(object)val2);
					return;
				}
				((Character)val3).m_name = "$gc_raidhen";
				((Character)val3).m_faction = (Faction)((!((Object)(object)component != (Object)null)) ? 2 : ((int)component.m_faction));
				((Character)val3).m_health = (((Object)(object)component != (Object)null) ? Mathf.Max(((Character)val3).m_health, component.m_health) : ((Character)val3).m_health);
				val3.m_defaultItems = component2.m_defaultItems;
				val3.m_randomWeapon = Array.Empty<GameObject>();
				val3.m_randomArmor = Array.Empty<GameObject>();
				val3.m_randomShield = Array.Empty<GameObject>();
				val3.m_randomSets = Array.Empty<ItemSet>();
				((Character)val3).m_tolerateWater = true;
				component4.m_enableHuntPlayer = true;
				component4.m_attackPlayerObjects = false;
				((BaseAI)component4).m_viewRange = Mathf.Max(((BaseAI)component3).m_viewRange, 30f);
				((BaseAI)component4).m_hearRange = Mathf.Max(((BaseAI)component3).m_hearRange, 30f);
				component4.m_alertRange = Mathf.Max(component3.m_alertRange, 20f);
				component4.m_fleeIfLowHealth = 0f;
				component4.m_fleeIfNotAlerted = false;
				component4.m_fleeIfHurtWhenTargetCantBeReached = false;
				((BaseAI)component4).m_avoidFire = false;
				((BaseAI)component4).m_afraidOfFire = false;
				component4.m_consumeItems = new List<ItemDrop>();
				component4.m_circleTargetInterval = component3.m_circleTargetInterval;
				component4.m_circleTargetDuration = component3.m_circleTargetDuration;
				component4.m_circleTargetDistance = component3.m_circleTargetDistance;
				component4.m_interceptTimeMin = component3.m_interceptTimeMin;
				component4.m_interceptTimeMax = component3.m_interceptTimeMax;
				component4.m_maxChaseDistance = component3.m_maxChaseDistance;
				component4.m_minAttackInterval = component3.m_minAttackInterval;
				PrefabManager.Instance.AddPrefab(new CustomPrefab(val2, false));
				prefab = val2;
				ServerPlugin.Log.LogInfo((object)string.Format("Kampfhühner: {0} angelegt (Leben {1:0}, Angriff des Wildschweins).", "GC_RaidHen", ((Character)val3).m_health));
			}
			catch (Exception arg)
			{
				ServerPlugin.Log.LogWarning((object)$"Kampfhühner: nicht angelegt: {arg}");
			}
		}

		private static Humanoid? MakeHumanoid(GameObject hen)
		{
			Character component = hen.GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			Humanoid val = (Humanoid)(object)((component is Humanoid) ? component : null);
			if (val != null)
			{
				return val;
			}
			Humanoid val2 = hen.AddComponent<Humanoid>();
			Type type = typeof(Character);
			while (type != null && type != typeof(MonoBehaviour))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					fieldInfo.SetValue(val2, fieldInfo.GetValue(component));
				}
				type = type.BaseType;
			}
			Object.DestroyImmediate((Object)(object)component);
			return val2;
		}

		internal static void AddEvent(RandEventSystem events)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			if (!((Object)(object)prefab == (Object)null) && !events.m_events.Any((RandomEvent e) => e != null && e.m_name == "gc_hen_raid"))
			{
				RandomEvent val = new RandomEvent
				{
					m_name = "gc_hen_raid",
					m_enabled = true,
					m_random = false,
					m_duration = 120f,
					m_nearBaseOnly = false,
					m_pauseIfNoPlayerInArea = true,
					m_eventRange = 96f,
					m_spawnerDelay = 2f,
					m_biome = (Biome)int.MaxValue,
					m_startMessage = "$gc_henraid_start",
					m_endMessage = "$gc_henraid_end",
					m_forceMusic = "gc_music_battle",
					m_forceEnvironment = ""
				};
				val.m_spawn.Add(new SpawnData
				{
					m_name = "GC_RaidHens",
					m_enabled = true,
					m_prefab = prefab,
					m_biome = (Biome)int.MaxValue,
					m_biomeArea = (BiomeArea)3,
					m_maxSpawned = 10,
					m_spawnInterval = 3f,
					m_spawnChance = 100f,
					m_spawnDistance = 4f,
					m_spawnRadiusMin = 8f,
					m_spawnRadiusMax = 25f,
					m_groupSizeMin = 3,
					m_groupSizeMax = 6,
					m_groupRadius = 4f,
					m_spawnAtDay = true,
					m_spawnAtNight = true,
					m_minAltitude = 0f,
					m_maxAltitude = 1000f,
					m_maxTilt = 45f,
					m_inForest = true,
					m_outsideForest = true,
					m_canSpawnCloseToPlayer = true,
					m_insidePlayerBase = true,
					m_huntPlayer = true,
					m_groundOffset = 0.5f,
					m_minLevel = 1,
					m_maxLevel = 3
				});
				events.m_events.Add(val);
			}
		}

		internal static bool Is(Character character)
		{
			ZNetView val = (((Object)(object)character != (Object)null) ? character.m_nview : null);
			ZDO val2 = (((Object)(object)val != (Object)null) ? val.GetZDO() : null);
			if (val2 != null)
			{
				return val2.GetPrefab() == PrefabHash;
			}
			return false;
		}

		internal static bool Peck(Humanoid hen, Character? target)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			ItemData currentWeapon = hen.GetCurrentWeapon();
			BaseAI baseAI = ((Character)hen).GetBaseAI();
			MonsterAI val = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
			Character val2 = (Character)(((Object)(object)target != (Object)null) ? ((object)target) : ((object)val?.m_targetCreature));
			if (currentWeapon == null || (Object)(object)val2 == (Object)null || !val2.IsPlayer() || val2.IsDead() || ((Character)hen).IsDead())
			{
				return false;
			}
			float num = currentWeapon.m_shared.m_aiAttackRange + val2.GetRadius() + ((Character)hen).GetRadius() + 0.4f;
			Vector3 val3 = ((Component)val2).transform.position - ((Component)hen).transform.position;
			if (((Vector3)(ref val3)).magnitude > num)
			{
				return false;
			}
			currentWeapon.m_lastAttackTime = Time.time;
			hen.m_timeSinceLastAttack = 0f;
			hen.m_lastCombatTimer = 0f;
			HitData val4 = new HitData();
			val4.m_damage = currentWeapon.GetDamage();
			((DamageTypes)(ref val4.m_damage)).Modify(1f + (float)Mathf.Max(0, ((Character)hen).GetLevel() - 1) * 0.5f);
			val4.m_point = val2.GetCenterPoint();
			val4.m_dir = ((Vector3)(ref val3)).normalized;
			val4.m_pushForce = currentWeapon.m_shared.m_attackForce;
			val4.m_backstabBonus = currentWeapon.m_shared.m_backstabBonus;
			val4.m_toolTier = (short)currentWeapon.m_shared.m_toolTier;
			val4.m_staggerMultiplier = 1f;
			val4.m_blockable = currentWeapon.m_shared.m_blockable;
			val4.m_dodgeable = currentWeapon.m_shared.m_dodgeable;
			val4.m_skill = currentWeapon.m_shared.m_skillType;
			val4.m_skillLevel = ((Character)hen).GetSkillLevel(currentWeapon.m_shared.m_skillType);
			val4.m_itemLevel = (short)currentWeapon.m_quality;
			val4.m_statusEffectHash = (((Object)(object)currentWeapon.m_shared.m_attackStatusEffect != (Object)null && (currentWeapon.m_shared.m_attackStatusEffectChance >= 1f || Random.value < currentWeapon.m_shared.m_attackStatusEffectChance)) ? currentWeapon.m_shared.m_attackStatusEffect.NameHash() : 0);
			val4.m_hitType = (HitType)1;
			val4.SetAttacker((Character)(object)hen);
			val2.Damage(val4);
			Rigidbody body = ((Character)hen).m_body;
			if ((Object)(object)body != (Object)null)
			{
				body.AddForce(Vector3.up * 3.2f + ((Vector3)(ref val3)).normalized * 2.2f, (ForceMode)2);
			}
			int instanceID = ((Object)hen).GetInstanceID();
			if (!LastCluck.TryGetValue(instanceID, out var value) || Time.time - value > 1.5f)
			{
				LastCluck[instanceID] = Time.time;
				Show.Local((Random.value < 0.5f) ? "sfx_chicken_idle_wingflap" : "sfx_chicken_hurt", ((Component)hen).transform.position, Quaternion.identity);
			}
			if (LastCluck.Count > 200)
			{
				LastCluck.Clear();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(RandEventSystem), "Awake")]
	internal static class RaidHenEventPatch
	{
		private static void Postfix(RandEventSystem __instance)
		{
			try
			{
				RaidHens.AddEvent(__instance);
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Kampfhühner: Raid nicht eingetragen: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	internal static class RaidHenAttackPatch
	{
		[HarmonyPriority(600)]
		private static bool Prefix(Humanoid __instance, Character target, ref bool __result)
		{
			if (!RaidHens.Is((Character)(object)__instance))
			{
				return true;
			}
			try
			{
				__result = RaidHens.Peck(__instance, target);
			}
			catch (Exception ex)
			{
				__result = false;
				ServerPlugin.Log.LogWarning((object)("Kampfhühner: Angriff: " + ex.Message));
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
	{
		typeof(Character),
		typeof(Character)
	})]
	internal static class RaidHenEnemyPatch
	{
		private static void Postfix(Character a, Character b, ref bool __result)
		{
			if (__result && !((Object)(object)a == (Object)null) && !((Object)(object)b == (Object)null))
			{
				if (RaidHens.Is(a))
				{
					__result = b.IsPlayer();
				}
				else if (RaidHens.Is(b))
				{
					__result = a.IsPlayer();
				}
			}
		}
	}
	internal sealed class CourierRunner : MonoBehaviour
	{
		private void OnDestroy()
		{
			Show.Unhush();
		}
	}
	internal static class Show
	{
		internal sealed class Dummy
		{
			public GameObject Root;

			public LineRenderer? Rope;

			public Transform? Line0;

			public Transform? Line1;

			public Transform? Attach;

			public GameObject[] Fragments = Array.Empty<GameObject>();

			public EffectList? Destroyed;

			public float Born;

			public float Lifetime = 600f;
		}

		internal sealed class Carrier
		{
			public GameObject Root;

			public Transform? HandPoint;

			public Animator? Animator;

			public float HoverHeight = 3f;

			public bool Bird;

			private float flapTimer;

			private float bank;

			public Vector3 Hand
			{
				get
				{
					//IL_0039: 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_0028: Unknown result type (might be due to invalid IL or missing references)
					//IL_002d: Unknown result type (might be due to invalid IL or missing references)
					if (!((Object)(object)HandPoint != (Object)null))
					{
						return Root.transform.position + Vector3.down * 2f;
					}
					return HandPoint.position;
				}
			}

			public static Carrier? Valkyrie(Vector3 cart)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: 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_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: 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_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = ValkyriePrefab();
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				Vector2 normalized = ((Vector2)(ref insideUnitCircle)).normalized;
				Vector3 val2 = cart + new Vector3(normalized.x, 0f, normalized.y) * 330f + Vector3.up * 170f;
				Carrier carrier = new Carrier
				{
					HoverHeight = 4f
				};
				GameObject val3 = Visual(val, val2, Quaternion.LookRotation(cart - val2), delegate(GameObject copy)
				{
					Valkyrie component = copy.GetComponent<Valkyrie>();
					if ((Object)(object)component != (Object)null)
					{
						carrier.HandPoint = component.m_attachPoint;
					}
				});
				if ((Object)(object)val3 == (Object)null)
				{
					return null;
				}
				carrier.Root = val3;
				carrier.Animator = val3.GetComponentInChildren<Animator>();
				if ((Object)(object)carrier.Animator != (Object)null)
				{
					carrier.Animator.SetBool("dropped", false);
				}
				return carrier;
			}

			public static Carrier? Seagull(Vector3 cart)
			{
				//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_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = Prefab("Seagal");
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				Vector2 normalized = ((Vector2)(ref insideUnitCircle)).normalized;
				Vector3 val2 = cart + new Vector3(normalized.x, 0f, normalized.y) * 200f + Vector3.up * 90f;
				Carrier carrier = new Carrier
				{
					HoverHeight = 1.5f,
					Bird = true
				};
				GameObject val3 = Visual(val, val2, Quaternion.LookRotation(cart - val2), delegate(GameObject copy)
				{
					RandomFlyingBird component = copy.GetComponent<RandomFlyingBird>();
					if ((Object)(object)component != (Object)null)
					{
						if ((Object)(object)component.m_landedModel != (Object)null)
						{
							component.m_landedModel.SetActive(false);
						}
						if ((Object)(object)component.m_flyingModel != (Object)null)
						{
							component.m_flyingModel.SetActive(true);
						}
					}
				});
				if ((Object)(object)val3 == (Object)null)
				{
					return null;
				}
				Transform transform = val3.transform;
				transform.localScale *= 3.5f;
				carrier.Root = val3;
				carrier.Animator = val3.GetComponentInChildren<Animator>();
				if ((Object)(object)carrier.Animator != (Object)null)
				{
					carrier.Animator.SetBool("flying", true);
					carrier.Animator.SetBool("flapping", true);
				}
				return carrier;
			}

			public void Fly(Vector3 position, Vector3 direction, float dt, float clearance = 0f)
			{
				//IL_004a: 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)
				//IL_0154: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: 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_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0117: 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_012e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Root == (Object)null)
				{
					return;
				}
				float num = default(float);
				if (clearance > 0f && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(position, ref num))
				{
					position.y = Mathf.Max(position.y, num + clearance);
				}
				Vector3 val = direction;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
				{
					Vector3 forward = Root.transform.forward;
					forward.y = 0f;
					float num2 = ((((Vector3)(ref forward)).sqrMagnitude > 0.0001f) ? Vector3.SignedAngle(forward, val, Vector3.up) : 0f);
					bank = Mathf.Lerp(bank, Mathf.Clamp((0f - num2) * 8f, -35f, 35f), dt * 2f);
					Quaternion val2 = Quaternion.LookRotation((((Vector3)(ref direction)).normalized.y > -0.9f) ? ((Vector3)(ref direction)).normalized : ((Vector3)(ref val)).normalized);
					Root.transform.rotation = Quaternion.Slerp(Root.transform.rotation, val2 * Quaternion.Euler(0f, 0f, bank), dt * 3f);
				}
				Root.transform.position = position;
				if (Bird && (Object)(object)Animator != (Object)null)
				{
					flapTimer -= dt;
					if (flapTimer <= 0f)
					{
						flapTimer = Random.Range(0.4f, 0.9f);
						Animator.SetBool("flapping", !Animator.GetBool("flapping") || direction.y > 0f);
					}
				}
			}
		}

		internal const float NormalCallSeconds = 5.5f;

		internal const float StrikeDelaySeconds = 3f;

		internal const float FinaleSeconds = 4.5f;

		internal const float ApproachSeconds = 12f;

		internal const float GrabSeconds = 2.5f;

		internal const float DepartSeconds = 10f;

		internal const float RopeLength = 6f;

		internal const float GrabGap = 0.5f;

		internal const float LiftSeconds = 1.5f;

		private const string StormEnv = "GC_CourierStorm";

		private static CourierRunner? runner;

		private static readonly Dictionary<long, Dummy> Waiting = new Dictionary<long, Dummy>();

		private static readonly Dictionary<long, (ZDOID record, ZPackage cargo)> Cargo = new Dictionary<long, (ZDOID, ZPackage)>();

		private static string? env;

		private static float envUntil;

		private static float envTransition = 1.2f;

		private static Vector3 envCenter;

		private static float envRange;

		private static bool transitionChanged;

		private static float savedTransition = 2f;

		private static string? music;

		private static float musicUntil;

		private static Vector3 musicCenter;

		private static float musicRange;

		private static string? raidEvent;

		private static Vector3 raidPosition;

		private static bool envsReady;

		private static GameObject? valkyriePrefab;

		private static bool valkyrieLoaded;

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

		private static float hushedFrom = -1f;

		private static GameObject? strikePrefab;

		private static bool strikeSearched;

		internal static readonly Dictionary<long, float> FinaleAt = new Dictionary<long, float>();

		internal static float CallSeconds(bool easter)
		{
			if (!easter)
			{
				return 5.5f;
			}
			return 44f;
		}

		internal static float PickupSeconds(bool easter)
		{
			return 26.5f;
		}

		internal static void Reset()
		{
			Unhush();
			Waiting.Clear();
			FinaleAt.Clear();
			Cargo.Clear();
			env = null;
			music = null;
			raidEvent = null;
			envsReady = false;
			runner = null;
			if (!Gc.IsHeadless)
			{
				Sounds.Load();
			}
		}

		internal static CourierRunner Runner()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)runner == (Object)null)
			{
				runner = new GameObject("GC_Courier").AddComponent<CourierRunner>();
			}
			return runner;
		}

		private static bool FromServer(long sender)
		{
			return sender == Transport.ServerUid();
		}

		private static bool Near(Vector3 position, float range = 150f)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				return Vector3.Distance(((Component)localPlayer).transform.position, position) <= range;
			}
			return false;
		}

		private static bool Mine(long peer)
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return peer == ZNet.GetUID();
			}
			return false;
		}

		internal static void Sky(string name, float seconds, float transition = 1.2f, Vector3 center = default(Vector3), float range = 0f)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			EnsureEnvironments();
			if (!((Object)(object)EnvMan.instance == (Object)null) && EnvMan.instance.GetEnv(name) != null)
			{
				env = name;
				envUntil = Time.time + seconds;
				envTransition = transition;
				envCenter = center;
				envRange = range;
			}
		}

		internal static void ClearSky()
		{
			envUntil = 0f;
		}

		internal static string? CurrentEnv()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			Player localPlayer = Player.m_localPlayer;
			bool flag = envRange <= 0f || ((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, envCenter) <= envRange);
			if (env != null && Time.time < envUntil && flag)
			{
				if ((Object)(object)instance != (Object)null)
				{
					if (!transitionChanged)
					{
						savedTransition = instance.m_transitionDuration;
						transitionChanged = true;
					}
					instance.m_transitionDuration = envTransition;
				}
				return env;
			}
			if (Time.time >= envUntil)
			{
				env = null;
			}
			if (transitionChanged && (Object)(object)instance != (Object)null && instance.m_transitionDuration != savedTransition)
			{
				instance.m_transitionDuration = Mathf.Max(savedTransition, 2f);
				transitionChanged = false;
			}
			return null;
		}

		internal static void Music(string name, float seconds, Vector3 center = default(Vector3), float range = 0f)
		{
			//IL_001a: 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)
			if (Sounds.HasMusic(name))
			{
				music = name;
				musicUntil = Time.time + seconds;
				musicCenter = center;
				musicRange = range;
			}
		}

		internal static string? CurrentMusic()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (music != null && Time.time < musicUntil)
			{
				Player localPlayer = Player.m_localPlayer;
				if (musicRange <= 0f || ((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, musicCenter) <= musicRange))
				{
					return music;
				}
				return null;
			}
			music = null;
			if (raidEvent != null && (Object)(object)RandEventSystem.instance != (Object)null)
			{
				RandomEvent activeEvent = RandEventSystem.instance.GetActiveEvent();
				if (activeEvent != null && activeEvent.m_name == raidEvent && Vector3.Distance(activeEvent.m_pos, raidPosition) < 2f && Sounds.HasMusic("gc_music_battle"))
				{
					return "gc_music_battle";
				}
				if (RandEventSystem.instance.GetCurrentRandomEvent() == null)
				{
					raidEvent = null;
				}
			}
			return null;
		}

		private static void EnsureEnvironments()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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)
			EnvMan instance = EnvMan.instance;
			if (envsReady || (Object)(object)instance == (Object)null)
			{
				return;
			}
			envsReady = true;
			try
			{
				EnvSetup val = instance.GetEnv("ThunderStorm");
				if (val != null)
				{
					Add(instance, Dark(val.Clone(), "GC_CourierStorm", new Color(0.05f, 0.06f, 0.09f), 0.035f, 0.12f));
					Add(instance, Dark(val.Clone(), "GC_CourierVoid", new Color(0.005f, 0.005f, 0.008f), 0.09f, 0.01f));
					Add(instance, Dark(val.Clone(), "GC_CourierBlood", new Color(0.3f, 0.02f, 0.02f), 0.05f, 0.25f));
					Add(instance, Dark(val.Clone(), "GC_CourierToxic", new Color(0.08f, 0.28f, 0.04f), 0.05f, 0.25f));
					Add(instance, Dark(val.Clone(), "GC_CourierGold", new Color(0.45f, 0.32f, 0.05f), 0.03f, 0.6f));
				}
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Walküren-Transport: eigene Wetter nicht angelegt: " + ex.Message));
			}
		}

		private static void Add(EnvMan man, EnvSetup setup)
		{
			if (man.GetEnv(setup.m_name) == null)
			{
				if (setup.m_psystems != null)
				{
					setup.m_psystems = (GameObject[])setup.m_psystems.Clone();
				}
				man.AppendEnvironment(setup);
				man.m_currentPSystems = null;
				man.m_currentEnvObject = null;
			}
		}

		private static EnvSetup Dark(EnvSetup env, string name, Color fog, float density, float light)
		{
			//IL_0017: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0033: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			env.m_name = name;
			env.m_default = false;
			env.m_alwaysDark = true;
			env.m_ambColorDay = (env.m_ambColorNight = fog * 1.3f);
			env.m_fogColorDay = (env.m_fogColorMorning = (env.m_fogColorEvening = (env.m_fogColorNight = fog)));
			env.m_fogColorSunDay = (env.m_fogColorSunMorning = (env.m_fogColorSunEvening = (env.m_fogColorSunNight = fog)));
			env.m_fogDensityDay = (env.m_fogDensityMorning = (env.m_fogDensityEvening = (env.m_fogDensityNight = density)));
			env.m_sunColorDay = (env.m_sunColorMorning = (env.m_sunColorEvening = (env.m_sunColorNight = fog * 2f)));
			env.m_lightIntensityDay = light;
			env.m_lightIntensityNight = light * 0.5f;
			return env;
		}

		internal static GameObject? Prefab(string name)
		{
			GameObject obj = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null);
			if ((Object)(object)obj == (Object)null && Missing.Add(name))
			{
				ServerPlugin.Log.LogInfo((object)("Walküren-Transport: Effekt „" + name + "“ gibt es nicht, er entfällt."));
			}
			return obj;
		}

		internal static GameObject? Local(string name, Vector3 position, Quaternion rotation, float scale = 1f, Transform? parent = null, float lifetime = 20f)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Prefab(name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = new GameObject("GC_CourierHolder");
			val2.SetActive(false);
			if ((Object)(object)parent != (Object)null)
			{
				val2.transform.SetParent(parent, false);
			}
			GameObject val3 = Object.Instantiate<GameObject>(val, position, rotation, val2.transform);
			MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val4 in componentsInChildren)
			{
				if ((val4 is Aoe || val4 is Projectile || val4 is TerrainOp || val4 is TerrainModifier || val4 is EffectArea || val4 is SpawnAbility || val4 is CinderSpawner || val4 is Fire || val4 is InstantiatePrefab) ? true : false)
				{
					Object.DestroyImmediate((Object)(object)val4);
				}
			}
			bool forceDisableTerrainOps = TerrainOp.m_forceDisableTerrainOps;
			ZNetView.m_forceDisableInit = true;
			TerrainOp.m_forceDisableTerrainOps = true;
			try
			{
				val3.transform.SetParent(parent, false);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
				TerrainOp.m_forceDisableTerrainOps = forceDisableTerrainOps;
				Object.Destroy((Object)(object)val2);
			}
			if (lifetime > 0f)
			{
				Object.Destroy((Object)(object)val3, lifetime);
			}
			if (scale != 1f)
			{
				Transform transform = val3.transform;
				transform.localScale *= scale;
			}
			return val3;
		}

		internal static IEnumerator Hush(float seconds)
		{
			if (hushedFrom < 0f)
			{
				hushedFrom = MusicMan.m_masterMusicVolume;
			}
			MusicMan.m_masterMusicVolume = hushedFrom * 0.05f;
			yield return (object)new WaitForSeconds(seconds);
			Unhush();
		}

		internal static void Unhush()
		{
			if (hushedFrom >= 0f)
			{
				MusicMan.m_masterMusicVolume = hushedFrom;
				hushedFrom = -1f;
			}
		}

		internal static void LocalEffects(EffectList? effects, Vector3 position, Quaternion rotation)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			if (effects == null)
			{
				return;
			}
			ZNetView.m_forceDisableInit = true;
			try
			{
				effects.Create(position, rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
		}

		internal static GameObject? Visual(GameObject? prefab, Vector3 position, Quaternion rotation, Action<GameObject>? read = null, bool keepAudio = true)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//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)
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("GC_CourierHolder");
			val.SetActive(false);
			GameObject val2 = Object.Instantiate<GameObject>(prefab, position, rotation, val.transform);
			try
			{
				read?.Invoke(val2);
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Walküren-Transport: " + ((Object)prefab).name + ": " + ex.Message));
			}
			Joint[] componentsInChildren = val2.GetComponentsInChildren<Joint>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			MonoBehaviour[] componentsInChildren2 = val2.GetComponentsInChildren<MonoBehaviour>(true);
			for (int num = componentsInChildren2.Length - 1; num >= 0; num--)
			{
				if ((Object)(object)componentsInChildren2[num] != (Object)null && !(componentsInChildren2[num] is AnimationEffect) && !(componentsInChildren2[num] is ZNetView))
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren2[num]);
				}
			}
			ZNetView[] componentsInChildren3 = val2.GetComponentsInChildren<ZNetView>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Rigidbody[] componentsInChildren4 = val2.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			Collider[] componentsInChildren5 = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[i]);
			}
			if (!keepAudio)
			{
				AudioSource[] componentsInChildren6 = val2.GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource obj in componentsInChildren6)
				{
					obj.playOnAwake = false;
					((Behaviour)obj).enabled = false;
				}
			}
			val2.transform.SetParent((Transform)null, true);
			Object.Destroy((Object)(object)val);
			val2.SetActive(true);
			return val2;
		}

		internal static Dummy? Cart(Vector3 position, Quaternion rotation, float fill)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Dummy dummy = new Dummy
			{
				Born = Time.time
			};
			GameObject val = Visual(Prefab("Cart"), position, rotation, delegate(GameObject copy)
			{
				Vagon component = copy.GetComponent<Vagon>();
				if ((Object)(object)component != (Object)null)
				{
					foreach (LoadData loadVi in component.m_loadVis)
					{
						if ((Object)(object)loadVi.m_gameobject != (Object)null)
						{
							loadVi.m_gameobject.SetActive(fill >= loadVi.m_minPercentage);
						}
					}
					dummy.Line0 = component.m_lineAttachPoints0;
					dummy.Line1 = component.m_lineAttachPoints1;
					dummy.Attach = component.m_attachPoint;
				}
				WearNTear component2 = copy.GetComponent<WearNTear>();
				if ((Object)(object)component2 != (Object)null)
				{
					if ((Object)(object)component2.m_new != (Object)null)
					{
						component2.m_new.SetActive(true);
					}
					if ((Object)(object)component2.m_worn != (Object)null)
					{
						component2.m_worn.SetActive(false);
					}
					if ((Object)(object)component2.m_broken != (Object)null)
					{
						component2.m_broken.SetActive(false);
					}
					dummy.Destroyed = component2.m_destroyedEffect;
					dummy.Fragments = component2.m_fragmentRoots ?? Array.Empty<GameObject>();
					GameObject[] fragments = dummy.Fragments;
					foreach (GameObject val2 in fragments)
					{
						if ((Object)(object)val2 != (Object)null)
						{
							val2.SetActive(false);
						}
					}
				}
				dummy.Rope = copy.GetComponent<LineRenderer>();
			}, keepAudio: false);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			dummy.Root = val;
			if ((Object)(object)dummy.Rope != (Object)null)
			{
				((Renderer)dummy.Rope).enabled = false;
			}
			return dummy;
		}

		internal static void Rope(Dummy cart, Vector3 to)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cart.Rope == (Object)null) && !((Object)(object)cart.Line0 == (Object)null) && !((Object)(object)cart.Line1 == (Object)null))
			{
				((Renderer)cart.Rope).enabled = true;
				cart.Rope.positionCount = 3;
				cart.Rope.SetPosition(0, cart.Line0.position);
				cart.Rope.SetPosition(1, to);
				cart.Rope.SetPosition(2, cart.Line1.position);
			}
		}

		internal static void Strike(Vector3 position, bool mine)
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if (!strikeSearched)
			{
				strikeSearched = true;
				GameObject? obj = Prefab("incinerator") ?? Prefab("piece_incinerator");
				Incinerator val = ((obj != null) ? obj.GetComponent<Incinerator>() : null);
				strikePrefab = (GameObject?)(((Object)(object)val != (Object)null && (Object)(object)val.m_lightingAOEs != (Object)null) ? ((object)val.m_lightingAOEs) : ((object)Prefab("lightningAOE")));
				ServerPlugin.Log.LogInfo((object)(((Object)(object)strikePrefab == (Object)null) ? "Walküren-Transport: Vernichter-Blitz nicht gefunden." : ("Walküren-Transport: Vernichter-Blitz „" + ((Object)strikePrefab).name + "“ (" + (((Object)(object)strikePrefab.GetComponent<ZNetView>() != (Object)null) ? "Netzobjekt" : "örtlich") + ").")));
			}
			if (!((Object)(object)strikePrefab == (Object)null) && (!((Object)(object)strikePrefab.GetComponent<ZNetView>() != (Object)null) || mine))
			{
				Object.Instantiate<GameObject>(strikePrefab, position, Quaternion.identity);
			}
		}

		internal static void Bolt(Vector3 ground, bool thunder = true, float scale = 1f)
		{
			//IL_0005: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Local("fx_Lightning", ground, Quaternion.identity, scale);
			if (thunder)
			{
				Local("sfx_thunder", ground, Quaternion.identity);
			}
		}

		internal static void Shake(Vector3 position, float strength, float range = 60f)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GameCamera.instance != (Object)null)
			{
				GameCamera.instance.AddShake(position, range, strength, false);
			}
		}

		internal static IEnumerator BlueFire(GameObject? target, float seconds, float scale = 2.2f)
		{
			if ((Object)(object)target == (Object)null)
			{
				yield break;
			}
			List<GameObject> fires = new List<GameObject>();
			Vector3[] array = (Vector3[])(object)new Vector3[3]
			{
				new Vector3(0f, 0.6f, 0.2f),
				new Vector3(0.45f, 0.7f, -0.5f),
				new Vector3(-0.45f, 0.7f, -0.5f)
			};
			foreach (Vector3 val in array)
			{
				GameObject val2 = Local("vfx_Burning_blue", target.transform.TransformPoint(val), target.transform.rotation, scale, target.transform, 0f);
				if ((Object)(object)val2 != (Object)null)
				{
					fires.Add(val2);
				}
			}
			GameObject glow = new GameObject("GC_CourierGlow");
			glow.transform.SetParent(target.transform, false);
			glow.transform.localPosition = new Vector3(0f, 1.2f, 0f);
			Light light = glow.AddComponent<Light>();
			light.type = (LightType)2;
			light.color = new Color(0.35f, 0.55f, 1f);
			light.range = 14f;
			float end = Time.time + seconds;
			while (Time.time < end && (Object)(object)glow != (Object)null)
			{
				light.intensity = 2.5f + Mathf.PerlinNoise(Time.time * 7f, 0.3f) * 2f;
				yield return null;
			}
			foreach (GameObject item in fires)
			{
				if (!((Object)(object)item == (Object)null))
				{
					ParticleSystem[] componentsInChildren = item.GetComponentsInChildren<ParticleSystem>();
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						componentsInChildren[i].Stop(true, (ParticleSystemStopBehavior)1);
					}
					Object.Destroy((Object)(object)item, 2.5f);
				}
			}
			float fade = 0f;
			while (fade < 1.5f && (Object)(object)glow != (Object)null)
			{
				fade += Time.deltaTime;
				light.intensity = Mathf.Lerp(2.5f, 0f, fade / 1.5f);
				yield return null;
			}
			if ((Object)(object)glow != (Object)null)
			{
				Object.Destroy((Object)(object)glow);
			}
			if ((Object)(object)target != (Object)null)
			{
				Local("vfx_Smoked", target.transform.position + Vector3.up, Quaternion.identity, 1f, null, 8f);
			}
		}

		internal static void OnCall(long sender, ZPackage pkg)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (Gc.IsHeadless || !FromServer(sender))
			{
				return;
			}
			long num = pkg.ReadLong();
			long peer = pkg.ReadLong();
			Vector3 val = pkg.ReadVector3();
			Quaternion rotation = pkg.ReadQuaternion();
			float fill = pkg.ReadSingle();
			bool flag = pkg.ReadBool();
			int waiting = pkg.ReadInt();
			bool flag2 = Mine(peer);
			if (!flag2 && !Near(val))
			{
				return;
			}
			if (!flag)
			{
				ValkyriePrefab();
			}
			Dummy dummy = Cart(val, rotation, fill);
			if (dummy != null)
			{
				if (Waiting.TryGetValue(num, out Dummy value) && (Object)(object)value.Root != (Object)null)
				{
					Object.Destroy((Object)(object)value.Root);
				}
				if (flag)
				{
					dummy.Lifetime = 3600f;
				}
				Waiting[num] = dummy;
			}
			((MonoBehaviour)Runner()).StartCoroutine(flag ? Easter.Call(val, dummy, flag2, num) : NormalCall(val, dummy, flag2, waiting));
		}

		private static IEnumerator NormalCall(Vector3 position, Dummy? cart, bool mine, int waiting)
		{
			//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)
			Sky("GC_CourierStorm", 5f, 1f);
			Local("sfx_distant thunder", position + Vector3.up * 40f, Quaternion.identity);
			Shake(position, 0.6f);
			yield return (object)new WaitForSeconds(3f);
			Strike(position, mine);
			Bolt(position, thunder: false, 1.4f);
			Local("sfx_thunder", position + Vector3.up * 3f, Quaternion.identity);
			Local("sfx_mistlands_thunder", position + Vector3.up * 10f, Quaternion.identity);
			Shake(position, 3f);
			if (cart != null)
			{
				((MonoBehaviour)Runner()).StartCoroutine(BlueFire(cart.Root, 3.2f));
			}
			yield return (object)new WaitForSeconds(Mathf.Max(0f, 2.5f));
			Local("sfx_thunder", position + new Vector3(30f, 50f, -20f), Quaternion.identity);
			if (mine && waiting > 0)
			{
				Gc.Center(GcLoc.Get("gccr_queued", new object[1] { waiting }));
			}
		}

		internal static void OnPickup(long sender, ZPackage pkg)
		{
			//IL_0018: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (Gc.IsHeadless || !FromServer(sender))
			{
				return;
			}
			long num = pkg.ReadLong();
			Vector3 position = pkg.ReadVector3();
			Quaternion rotation = pkg.ReadQuaternion();
			float fill = pkg.ReadSingle();
			bool easter = pkg.ReadBool();
			float delay = pkg.ReadSingle();
			if (!Near(position, 210f))
			{
				if (Waiting.TryGetValue(num, out Dummy value) && (Object)(object)value.Root != (Object)null)
				{
					Object.Destroy((Object)(object)value.Root);
				}
				Waiting.Remove(num);
			}
			else
			{
				((MonoBehaviour)Runner()).StartCoroutine(Pickup(num, position, rotation, fill, easter, delay));
			}
		}

		private static IEnumerator Pickup(long playerId, Vector3 position, Quaternion rotation, float fill, bool easter, 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)
			//IL_0015: 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)
			if (delay > 0f)
			{
				yield return (object)new WaitForSeconds(delay);
			}
			if (!Waiting.TryGetValue(playerId, out Dummy cart) || (Object)(object)cart.Root == (Object)null)
			{
				Dummy dummy = Cart(position, rotation, fill);
				if (dummy == null)
				{
					yield break;
				}
				cart = dummy;
			}
			Waiting.Remove(playerId);
			Carrier carrier = (easter ? Carrier.Seagull(position) : Carrier.Valkyrie(position));

GC_Zuchtgrenze.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GC.Server.Leash;
using GC.Shared;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Gorduan")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.1.0")]
[assembly: AssemblyInformationalVersion("1.8.1+7c8bde9391283b12125175d68f4632c4cf8f93b3")]
[assembly: AssemblyProduct("GC_Zuchtgrenze")]
[assembly: AssemblyTitle("GC_Zuchtgrenze")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GC.Server
{
	internal static class ServerPlugin
	{
		internal static ManualLogSource Log;

		internal static GcModule? Module;

		internal static bool Allowed
		{
			get
			{
				if (Module != null)
				{
					return Module.Allowed;
				}
				return true;
			}
		}

		internal static bool OnServer
		{
			get
			{
				if (Module != null)
				{
					return Module.OnServer;
				}
				return false;
			}
		}
	}
}
namespace GC.Server.ModZuchtgrenze
{
	[BepInPlugin("gorduan.gc.zuchtgrenze", "GC_Zuchtgrenze", "1.8.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static GcModule Module;

		private void Awake()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Module = GcKern.Register((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, GcMod.Info);
			ServerPlugin.Log = ((BaseUnityPlugin)this).Logger;
			ServerPlugin.Module = Module;
			Harmony val = new Harmony("gorduan.gc.zuchtgrenze");
			BreedLimit.Init(((BaseUnityPlugin)this).Config);
			Module.TakeOverOldSettings();
			Module.IsOn = () => BreedLimit.Enabled.Value;
			val.PatchAll(typeof(Plugin).Assembly);
			Module.MenuGroup((Func<string, string>)((string key) => GcLoc.Get("gcsv_" + key, Array.Empty<object>())), (string)null).Main("breed", (ConfigEntryBase)(object)BreedLimit.Enabled, (Func<bool>)null, "", (Func<string>)null, 0.0, "", (Func<bool>)null, (Func<bool>)null).Sub("breed_factor", (ConfigEntryBase)(object)BreedLimit.LimitFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("breed_radius", (ConfigEntryBase)(object)BreedLimit.RadiusFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("breed_leashed", (ConfigEntryBase)(object)BreedLimit.LeashedCount, 0.1, "", (Func<bool>)null, "", (Func<bool>)(() => GcKern.ModLoaded("tiere")), (Func<bool>)null)
				.Sub("breed_chicken_factor", (ConfigEntryBase)(object)BreedLimit.ChickenLimitFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("breed_chicken_radius", (ConfigEntryBase)(object)BreedLimit.ChickenRadiusFactor, 0.1, " ×", (Func<bool>)null, "", (Func<bool>)null, (Func<bool>)null)
				.Sub("breed_chicken_leashed", (ConfigEntryBase)(object)BreedLimit.ChickenLeashedCount, 0.1, "", (Func<bool>)null, "", (Func<bool>)(() => GcKern.ModLoaded("tiere")), (Func<bool>)null);
		}
	}
	internal static class GcMod
	{
		public const string Id = "zuchtgrenze";

		public const string Guid = "gorduan.gc.zuchtgrenze";

		public const string Name = "GC_Zuchtgrenze";

		public const string Version = "1.8.1";

		public const int Stufe = 4;

		public static GcModInfo Info
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				GcModInfo val = new GcModInfo();
				val.Id = "zuchtgrenze";
				val.Guid = "gorduan.gc.zuchtgrenze";
				val.Name = "GC_Zuchtgrenze";
				val.Version = "1.8.1";
				val.Stufe = 4;
				val.Seite = (GcSeite)2;
				val.Braucht = Array.Empty<string>();
				val.Partner = new string[1] { "tiere" };
				val.Fremd = Array.Empty<string>();
				val.AlteConfig = "gorduan.gc_server.cfg";
				val.Ausgleich = 1f;
				return val;
			}
		}
	}
}
namespace GC.Server.Leash
{
	internal static class BreedLimit
	{
		private const string ChickenPrefab = "Hen";

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<float> LimitFactor = null;

		internal static ConfigEntry<float> RadiusFactor = null;

		internal static ConfigEntry<float> LeashedCount = null;

		internal static ConfigEntry<float> ChickenLimitFactor = null;

		internal static ConfigEntry<float> ChickenRadiusFactor = null;

		internal static ConfigEntry<float> ChickenLeashedCount = null;

		private static bool reported;

		private static readonly int LeashHolderHash = StringExtensionMethods.GetStableHashCode("gc_leash_holder");

		private static readonly int LeashTiedHash = StringExtensionMethods.GetStableHashCode("gc_leash_tied");

		internal static void Init(ConfigFile Config)
		{
			Enabled = Gc.BindSynced<bool>(Config, "9 - Breeding", "Enabled", true, "Eigene Zuchtgrenze: Valheim lässt Tiere nur Junge bekommen, solange im Umkreis nicht zu viele ihrer Art stehen (z. B. 4 Wölfe in 10 m; Junge und wilde Tiere zählen mit). Aus: wie Valheim.", (AcceptableValueBase)null);
			LimitFactor = Gc.BindSynced<float>(Config, "9 - Breeding", "LimitFactor", 1.5f, "Faktor auf Valheims Grenze je Tierart (1,5: aus 4 Wölfen werden 6). Nicht für Hühner.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f));
			RadiusFactor = Gc.BindSynced<float>(Config, "9 - Breeding", "RadiusFactor", 1f, "Faktor auf Valheims Umkreis, in dem gezählt wird (1 = wie Valheim, z. B. 10 m bei Wölfen). Nicht für Hühner.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f));
			LeashedCount = Gc.BindSynced<float>(Config, "9 - Breeding", "LeashedCount", 0.5f, "So viel zählt ein Tier an einer Leine oder an einem Pfosten (0,5 = halb, 1 = voll wie Valheim). Nicht für Hühner.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f));
			ChickenLimitFactor = Gc.BindSynced<float>(Config, "9 - Breeding", "ChickenLimitFactor", 1f, "Hühner: Faktor auf Valheims Grenze (gezählt werden Hennen und gelegte Eier). 1 = wie Valheim.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f));
			ChickenRadiusFactor = Gc.BindSynced<float>(Config, "9 - Breeding", "ChickenRadiusFactor", 1f, "Hühner: Faktor auf Valheims Umkreis. 1 = wie Valheim.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f));
			ChickenLeashedCount = Gc.BindSynced<float>(Config, "9 - Breeding", "ChickenLeashedCount", 1f, "Hühner: so viel zählt eine Henne an einer Leine oder an einem Pfosten. 1 = wie Valheim.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f));
		}

		internal static void Apply(Procreation procreation)
		{
			//IL_0143: 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_0155: 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)
			try
			{
				if (!Enabled.Value || (Object)(object)ZNetScene.instance == (Object)null)
				{
					return;
				}
				ZNetView nview = procreation.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner() || (Object)(object)procreation.m_tameable == (Object)null || !procreation.m_tameable.IsTamed() || procreation.IsPregnant())
				{
					return;
				}
				GameObject prefab = ZNetScene.instance.GetPrefab(nview.GetZDO().GetPrefab());
				if (!((Object)(object)prefab == (Object)null))
				{
					bool num = ((Object)prefab).name == "Hen";
					float num2 = (num ? ChickenLimitFactor.Value : LimitFactor.Value);
					float num3 = (num ? ChickenRadiusFactor.Value : RadiusFactor.Value);
					float num4 = (num ? ChickenLeashedCount.Value : LeashedCount.Value);
					if (!Mathf.Approximately(num2, 1f) || !Mathf.Approximately(num3, 1f) || !Mathf.Approximately(num4, 1f))
					{
						GameObject prefab2 = (((Object)(object)procreation.m_offspring != (Object)null) ? ZNetScene.instance.GetPrefab(Utils.GetPrefabName(procreation.m_offspring)) : null);
						Vector3 position = ((Component)procreation).transform.position;
						float range = procreation.m_totalCheckRange * num3;
						float num5 = Count(prefab, position, range, num4) + Count(prefab2, position, range, num4);
						procreation.m_maxCreatures = ((num5 < (float)procreation.m_maxCreatures * num2) ? int.MaxValue : 0);
					}
				}
			}
			catch (Exception arg)
			{
				if (!reported)
				{
					reported = true;
					ServerPlugin.Log.LogWarning((object)$"Zuchtgrenze: {arg}");
				}
			}
		}

		private static float Count(GameObject? prefab, Vector3 center, float range, float leashed)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return 0f;
			}
			if ((Object)(object)prefab.GetComponent<BaseAI>() == (Object)null)
			{
				return SpawnSystem.GetNrOfInstances(prefab, center, range, false, false);
			}
			string text = ((Object)prefab).name + "(Clone)";
			float num = 0f;
			foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
			{
				if (!((Object)(object)baseAIInstance == (Object)null) && !(((Object)((Component)baseAIInstance).gameObject).name != text) && (!(range > 0f) || !(Vector3.Distance(center, ((Component)baseAIInstance).transform.position) > range)))
				{
					num += (OnLeash(baseAIInstance) ? leashed : 1f);
				}
			}
			return num;
		}

		private static bool OnLeash(BaseAI ai)
		{
			ZNetView nview = ai.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			ZDO zDO = nview.GetZDO();
			if (zDO.GetLong(LeashHolderHash, 0L) == 0L)
			{
				return zDO.GetInt(LeashTiedHash, 0) == 1;
			}
			return true;
		}

		internal static void LogLimits(ZNetScene scene)
		{
			List<string> list = new List<string>();
			foreach (GameObject prefab in scene.m_prefabs)
			{
				Procreation val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Procreation>() : null);
				if (!((Object)(object)val == (Object)null))
				{
					bool num = ((Object)prefab).name == "Hen";
					float num2 = (num ? ChickenLimitFactor.Value : LimitFactor.Value);
					float num3 = (num ? ChickenRadiusFactor.Value : RadiusFactor.Value);
					list.Add(string.Format(CultureInfo.InvariantCulture, "{0} {1} in {2:0.#} m → {3:0.#} in {4:0.#} m", ((Object)prefab).name, val.m_maxCreatures, val.m_totalCheckRange, (float)val.m_maxCreatures * num2, val.m_totalCheckRange * num3));
				}
			}
			ServerPlugin.Log.LogInfo((object)string.Format("Zuchtgrenze ({0}, an der Leine zählt ein Tier {1:0.##}, eine Henne {2:0.##}): {3}", Enabled.Value ? "an" : "aus", LeashedCount.Value, ChickenLeashedCount.Value, string.Join(", ", list)));
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class BreedLimitPatch
	{
		private static void Prefix(Procreation __instance, out int __state)
		{
			__state = __instance.m_maxCreatures;
			BreedLimit.Apply(__instance);
		}

		private static Exception? Finalizer(Procreation __instance, int __state, Exception? __exception)
		{
			__instance.m_maxCreatures = __state;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class BreedLimitLogPatch
	{
		private static bool logged;

		private static void Postfix(ZNetScene __instance)
		{
			if (logged)
			{
				return;
			}
			logged = true;
			try
			{
				BreedLimit.LogLimits(__instance);
			}
			catch (Exception ex)
			{
				ServerPlugin.Log.LogWarning((object)("Zuchtgrenze: Liste nicht geschrieben: " + ex.Message));
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}