Decompiled source of MCZombieLegacyCompat v1.1.0

patchers/MCZombieLegacyCompat/MCZombieLegacyCompat.Patcher.dll

Decompiled a week 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 BepInEx;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MCZombieLegacyCompat.Patcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("MCZombieLegacyCompat.Patcher")]
[assembly: AssemblyTitle("MCZombieLegacyCompat.Patcher")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace CaptainTeam.MCZombieCompat;

internal sealed class LegacyRewriter
{
	internal const string MarkerTypeName = "CaptainTeam.MCZombieCompat.PatchedMarker";

	private const string ShimTypeName = "CaptainTeam.MCZombieCompat.Shims.PaintedUtilsShims";

	private readonly ModuleDefinition _module;

	private readonly ModuleDefinition _shims;

	private readonly Action<string> _log;

	private readonly Dictionary<string, MethodDefinition> _copiedShims = new Dictionary<string, MethodDefinition>();

	private TypeDefinition _shimHost;

	internal LegacyRewriter(ModuleDefinition module, ModuleDefinition shims, Action<string> log)
	{
		_module = module;
		_shims = shims;
		_log = log;
	}

	internal static bool IsPatched(ModuleDefinition module)
	{
		return ((IEnumerable<TypeDefinition>)module.Types).Any((TypeDefinition t) => ((MemberReference)t).FullName == "CaptainTeam.MCZombieCompat.PatchedMarker");
	}

	internal int Rewrite()
	{
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Expected O, but got Unknown
		int num = 0;
		foreach (TypeDefinition item in _module.GetTypes().ToList())
		{
			foreach (MethodDefinition item2 in ((IEnumerable<MethodDefinition>)item.Methods).Where((MethodDefinition m) => m.HasBody).ToList())
			{
				num += RewriteMethod(item2);
			}
		}
		if (num > 0)
		{
			_module.Types.Add(new TypeDefinition("CaptainTeam.MCZombieCompat", "PatchedMarker", (TypeAttributes)384, _module.TypeSystem.Object));
		}
		return num;
	}

	private int RewriteMethod(MethodDefinition method)
	{
		int num = 0;
		ILProcessor iLProcessor = method.Body.GetILProcessor();
		foreach (Instruction item in ((IEnumerable<Instruction>)method.Body.Instructions).ToList())
		{
			object operand = item.Operand;
			MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
			if (val != null && !(val is MethodDefinition) && !Resolves((MemberReference)(object)val))
			{
				if (TryRewriteCall(method, iLProcessor, item, val))
				{
					num++;
					_log("  " + ((MemberReference)method.DeclaringType).Name + "::" + ((MemberReference)method).Name + " -> " + ((MemberReference)((MemberReference)val).DeclaringType).Name + "." + ((MemberReference)val).Name);
				}
				continue;
			}
			object operand2 = item.Operand;
			FieldReference val2 = (FieldReference)((operand2 is FieldReference) ? operand2 : null);
			if (val2 != null && !(val2 is FieldDefinition) && !Resolves((MemberReference)(object)val2) && TryRewriteField(iLProcessor, item, val2))
			{
				num++;
				_log("  " + ((MemberReference)method.DeclaringType).Name + "::" + ((MemberReference)method).Name + " -> " + ((MemberReference)((MemberReference)val2).DeclaringType).Name + "." + ((MemberReference)val2).Name);
			}
		}
		return num;
	}

	private bool TryRewriteCall(MethodDefinition method, ILProcessor il, Instruction ins, MethodReference mref)
	{
		//IL_0094: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		string fullName = ((MemberReference)((MemberReference)mref).DeclaringType).FullName;
		string[] array = ((IEnumerable<ParameterDefinition>)mref.Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).ToArray();
		if (fullName == "EnemyNavMeshAgent" && ((MemberReference)mref).Name == "Warp" && array.Length == 1)
		{
			MethodReference val = FindMethod(((MemberReference)mref).DeclaringType, "Warp", "UnityEngine.Vector3", "System.Boolean");
			if (val == null)
			{
				return false;
			}
			Instruction val2 = il.Create(ins.OpCode, val);
			ReplaceWith(il, ins, il.Create(OpCodes.Ldc_I4_0), val2);
			return true;
		}
		if (fullName == "PhysGrabber" && ((MemberReference)mref).Name == "ReleaseObject" && array.Length == 1 && array[0] == "System.Single")
		{
			MethodReference val3 = FindMethod(((MemberReference)mref).DeclaringType, "ReleaseObject", "System.Int32", "System.Single");
			if (val3 == null)
			{
				return false;
			}
			VariableDefinition val4 = new VariableDefinition(_module.TypeSystem.Single);
			method.Body.Variables.Add(val4);
			method.Body.InitLocals = true;
			ReplaceWith(il, ins, il.Create(OpCodes.Stloc, val4), il.Create(OpCodes.Ldc_I4_M1), il.Create(OpCodes.Ldloc, val4), il.Create(ins.OpCode, val3));
			return true;
		}
		if (fullName == "REPOLib.Modules.NetworkPrefabs" && ((MemberReference)mref).Name == "SpawnNetworkPrefab" && array.Length == 5 && array[0] == "System.String")
		{
			return RedirectToShim(il, ins, "SpawnNetworkPrefabById");
		}
		if (fullName == "REPOLib.Modules.Valuables" && ((MemberReference)mref).Name == "SpawnValuable" && array.Length == 3 && array[0] == "ValuableObject")
		{
			return RedirectToShim(il, ins, "SpawnValuableObject");
		}
		if (fullName == "REPOLib.Modules.NetworkPrefabs" && ((MemberReference)mref).Name == "RegisterNetworkPrefab" && array.Length == 1 && ((MemberReference)mref.ReturnType).FullName == "System.Void")
		{
			return RedirectToShim(il, ins, "RegisterNetworkPrefab");
		}
		return false;
	}

	private bool TryRewriteField(ILProcessor il, Instruction ins, FieldReference fref)
	{
		//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_00b0: 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)
		if (((MemberReference)((MemberReference)fref).DeclaringType).FullName == "PlayerAvatar" && ((MemberReference)fref).Name == "localCameraTransform" && ins.OpCode == OpCodes.Ldfld)
		{
			TypeDefinition obj = ((MemberReference)fref).DeclaringType.Resolve();
			FieldDefinition val = ((obj != null) ? ((IEnumerable<FieldDefinition>)obj.Fields).FirstOrDefault((Func<FieldDefinition, bool>)((FieldDefinition f) => ((MemberReference)f).Name == "localCamera")) : null);
			if (val == null)
			{
				return false;
			}
			MethodDefinition val2 = FindInHierarchy(((FieldReference)val).FieldType.Resolve(), "UnityEngine.Component", "get_transform");
			if (val2 == null)
			{
				return false;
			}
			ReplaceWith(il, ins, il.Create(OpCodes.Ldfld, _module.ImportReference((FieldReference)(object)val)), il.Create(OpCodes.Callvirt, _module.ImportReference((MethodReference)(object)val2)));
			return true;
		}
		return false;
	}

	private static void ReplaceWith(ILProcessor il, Instruction ins, params Instruction[] replacement)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		ins.OpCode = replacement[0].OpCode;
		ins.Operand = replacement[0].Operand;
		Instruction val = ins;
		for (int i = 1; i < replacement.Length; i++)
		{
			il.InsertAfter(val, replacement[i]);
			val = replacement[i];
		}
	}

	private bool RedirectToShim(ILProcessor il, Instruction ins, string shimName)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		MethodDefinition orCopyShim = GetOrCopyShim(shimName);
		if (orCopyShim == null)
		{
			return false;
		}
		ins.OpCode = OpCodes.Call;
		ins.Operand = orCopyShim;
		return true;
	}

	private MethodReference FindMethod(TypeReference owner, string name, params string[] parameterTypes)
	{
		TypeDefinition obj = owner.Resolve();
		MethodDefinition val = ((obj != null) ? ((IEnumerable<MethodDefinition>)obj.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition x) => ((MemberReference)x).Name == name && ((IEnumerable<ParameterDefinition>)((MethodReference)x).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).SequenceEqual(parameterTypes))) : null);
		if (val != null)
		{
			return _module.ImportReference((MethodReference)(object)val);
		}
		return null;
	}

	private static MethodDefinition FindInHierarchy(TypeDefinition type, string declaringType, string name)
	{
		while (type != null)
		{
			if (((MemberReference)type).FullName == declaringType)
			{
				return ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == name && !((MethodReference)m).HasParameters));
			}
			TypeReference baseType = type.BaseType;
			type = ((baseType != null) ? baseType.Resolve() : null);
		}
		return null;
	}

	private static bool Resolves(MemberReference member)
	{
		try
		{
			MethodReference val = (MethodReference)(object)((member is MethodReference) ? member : null);
			if (val == null)
			{
				FieldReference val2 = (FieldReference)(object)((member is FieldReference) ? member : null);
				if (val2 != null)
				{
					return val2.Resolve() != null;
				}
				return true;
			}
			return val.Resolve() != null;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private MethodDefinition GetOrCopyShim(string name)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		if (_copiedShims.TryGetValue(name, out var value))
		{
			return value;
		}
		TypeDefinition type = _shims.GetType("CaptainTeam.MCZombieCompat.Shims.PaintedUtilsShims");
		MethodDefinition val = ((type != null) ? ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == name)) : null);
		if (val == null)
		{
			return null;
		}
		if (_shimHost == null)
		{
			_shimHost = new TypeDefinition("CaptainTeam.MCZombieCompat", "PaintedUtilsShims", (TypeAttributes)1048961, _module.TypeSystem.Object);
			_module.Types.Add(_shimHost);
		}
		MethodDefinition val2 = CopyMethod(val);
		_shimHost.Methods.Add(val2);
		_copiedShims[name] = val2;
		return val2;
	}

	private MethodDefinition CopyMethod(MethodDefinition src)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//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_0050: 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_006e: Expected O, but got Unknown
		//IL_00af: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Expected O, but got Unknown
		//IL_0151: 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_0163: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_038a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Expected O, but got Unknown
		MethodDefinition val = new MethodDefinition(((MemberReference)src).Name, src.Attributes, _module.ImportReference(((MethodReference)src).ReturnType));
		Dictionary<ParameterDefinition, ParameterDefinition> dictionary = new Dictionary<ParameterDefinition, ParameterDefinition>();
		Enumerator<ParameterDefinition> enumerator = ((MethodReference)src).Parameters.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				ParameterDefinition current = enumerator.Current;
				ParameterDefinition val2 = new ParameterDefinition(((ParameterReference)current).Name, current.Attributes, _module.ImportReference(((ParameterReference)current).ParameterType));
				((MethodReference)val).Parameters.Add(val2);
				dictionary[current] = val2;
			}
		}
		finally
		{
			((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
		}
		Dictionary<VariableDefinition, VariableDefinition> dictionary2 = new Dictionary<VariableDefinition, VariableDefinition>();
		Enumerator<VariableDefinition> enumerator2 = src.Body.Variables.GetEnumerator();
		try
		{
			while (enumerator2.MoveNext())
			{
				VariableDefinition current2 = enumerator2.Current;
				VariableDefinition val3 = new VariableDefinition(_module.ImportReference(((VariableReference)current2).VariableType));
				val.Body.Variables.Add(val3);
				dictionary2[current2] = val3;
			}
		}
		finally
		{
			((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
		}
		val.Body.InitLocals = src.Body.InitLocals;
		val.Body.MaxStackSize = src.Body.MaxStackSize;
		Dictionary<Instruction, Instruction> insMap = new Dictionary<Instruction, Instruction>();
		Enumerator<Instruction> enumerator3 = src.Body.Instructions.GetEnumerator();
		try
		{
			while (enumerator3.MoveNext())
			{
				Instruction current3 = enumerator3.Current;
				Instruction val4 = Instruction.Create(OpCodes.Nop);
				val4.OpCode = current3.OpCode;
				insMap[current3] = val4;
				val.Body.Instructions.Add(val4);
			}
		}
		finally
		{
			((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
		}
		enumerator3 = src.Body.Instructions.GetEnumerator();
		try
		{
			while (enumerator3.MoveNext())
			{
				Instruction current4 = enumerator3.Current;
				Instruction val5 = insMap[current4];
				object operand = current4.Operand;
				Instruction val6 = (Instruction)((operand is Instruction) ? operand : null);
				if (val6 == null)
				{
					if (!(operand is Instruction[] source))
					{
						VariableDefinition val7 = (VariableDefinition)((operand is VariableDefinition) ? operand : null);
						if (val7 == null)
						{
							ParameterDefinition val8 = (ParameterDefinition)((operand is ParameterDefinition) ? operand : null);
							if (val8 == null)
							{
								MethodReference val9 = (MethodReference)((operand is MethodReference) ? operand : null);
								if (val9 == null)
								{
									FieldReference val10 = (FieldReference)((operand is FieldReference) ? operand : null);
									if (val10 == null)
									{
										TypeReference val11 = (TypeReference)((operand is TypeReference) ? operand : null);
										if (val11 != null)
										{
											val5.Operand = _module.ImportReference(val11);
										}
										else
										{
											val5.Operand = current4.Operand;
										}
									}
									else
									{
										val5.Operand = _module.ImportReference(val10);
									}
								}
								else
								{
									val5.Operand = _module.ImportReference(val9);
								}
							}
							else
							{
								val5.Operand = dictionary[val8];
							}
						}
						else
						{
							val5.Operand = dictionary2[val7];
						}
					}
					else
					{
						val5.Operand = source.Select((Instruction t) => insMap[t]).ToArray();
					}
				}
				else
				{
					val5.Operand = insMap[val6];
				}
			}
		}
		finally
		{
			((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
		}
		Enumerator<ExceptionHandler> enumerator4 = src.Body.ExceptionHandlers.GetEnumerator();
		try
		{
			while (enumerator4.MoveNext())
			{
				ExceptionHandler current5 = enumerator4.Current;
				val.Body.ExceptionHandlers.Add(new ExceptionHandler(current5.HandlerType)
				{
					TryStart = Map(insMap, current5.TryStart),
					TryEnd = Map(insMap, current5.TryEnd),
					HandlerStart = Map(insMap, current5.HandlerStart),
					HandlerEnd = Map(insMap, current5.HandlerEnd),
					FilterStart = Map(insMap, current5.FilterStart),
					CatchType = ((current5.CatchType == null) ? null : _module.ImportReference(current5.CatchType))
				});
			}
			return val;
		}
		finally
		{
			((IDisposable)enumerator4/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static Instruction Map(Dictionary<Instruction, Instruction> map, Instruction i)
	{
		if (i != null)
		{
			return map[i];
		}
		return null;
	}
}
public static class Patcher
{
	private static readonly string[] Targets = new string[2] { "MCZombieMod.dll", "PaintedUtils.dll" };

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

	public static IEnumerable<string> TargetDLLs => new string[0];

	public static void Patch(AssemblyDefinition assembly)
	{
	}

	public static void Initialize()
	{
		try
		{
			ModuleDefinition shims = LoadShims();
			string[] targets = Targets;
			foreach (string searchPattern in targets)
			{
				string[] files = Directory.GetFiles(Paths.PluginPath, searchPattern, SearchOption.AllDirectories);
				for (int j = 0; j < files.Length; j++)
				{
					PatchFile(files[j], shims);
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Patcher failed: " + ex));
		}
	}

	private static void PatchFile(string path, ModuleDefinition shims)
	{
		//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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		try
		{
			DefaultAssemblyResolver val = CreateResolver();
			try
			{
				using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(path));
				ModuleDefinition val2 = ModuleDefinition.ReadModule((Stream)memoryStream, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)val,
					ReadingMode = (ReadingMode)1
				});
				try
				{
					if (LegacyRewriter.IsPatched(val2))
					{
						Log.LogInfo((object)(Path.GetFileName(path) + ": already patched."));
						return;
					}
					List<string> list = new List<string>();
					int num = new LegacyRewriter(val2, shims, list.Add).Rewrite();
					if (num == 0)
					{
						Log.LogInfo((object)(Path.GetFileName(path) + ": no legacy call sites found, left untouched."));
						return;
					}
					MemoryStream memoryStream2 = new MemoryStream();
					val2.Write((Stream)memoryStream2);
					string text = path + ".ctbak";
					if (!File.Exists(text))
					{
						File.Copy(path, text);
					}
					File.WriteAllBytes(path, memoryStream2.ToArray());
					Log.LogInfo((object)(Path.GetFileName(path) + ": " + num + " legacy call site(s) rewritten (backup: " + Path.GetFileName(text) + ")."));
					foreach (string item in list)
					{
						Log.LogDebug((object)item);
					}
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)(Path.GetFileName(path) + ": rewrite failed, file left untouched: " + ex));
		}
	}

	private static DefaultAssemblyResolver CreateResolver()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		DefaultAssemblyResolver val = new DefaultAssemblyResolver();
		((BaseAssemblyResolver)val).AddSearchDirectory(Paths.ManagedPath);
		((BaseAssemblyResolver)val).AddSearchDirectory(Paths.BepInExAssemblyDirectory);
		((BaseAssemblyResolver)val).AddSearchDirectory(Paths.PluginPath);
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "*", SearchOption.AllDirectories);
		foreach (string text in directories)
		{
			((BaseAssemblyResolver)val).AddSearchDirectory(text);
		}
		return val;
	}

	private static ModuleDefinition LoadShims()
	{
		//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_0041: Expected O, but got Unknown
		using Stream stream = typeof(Patcher).Assembly.GetManifestResourceStream("MCZombieCompatShims.dll");
		MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		memoryStream.Position = 0L;
		return ModuleDefinition.ReadModule((Stream)memoryStream, new ReaderParameters
		{
			ReadingMode = (ReadingMode)1
		});
	}
}

plugins/MCZombieLegacyCompat/MCZombieFix.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MCZombieFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("MCZombieFix")]
[assembly: AssemblyTitle("MCZombieFix")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MCZombieFix
{
	internal static class EnemyRegistration
	{
		internal static object LastMCZombieSetup { get; private set; }

		internal static void RegisterEnemy(object setup)
		{
			if (setup != null)
			{
				LastMCZombieSetup = setup;
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase));
				if (assembly == null)
				{
					throw new InvalidOperationException("REPOLib assembly not loaded.");
				}
				Type enemyContentType = assembly.GetType("REPOLib.Objects.Sdk.EnemyContent", throwOnError: false);
				Type type = assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false);
				if (enemyContentType == null || type == null)
				{
					throw new MissingMemberException("REPOLib 4 EnemyContent/Enemies type not found.");
				}
				object obj = CreateScriptableObject(enemyContentType);
				if (obj == null)
				{
					throw new InvalidOperationException("Could not create EnemyContent.");
				}
				FieldInfo? field = enemyContentType.GetField("_setup", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = enemyContentType.GetField("_spawnObjects", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null || field2 == null)
				{
					throw new MissingFieldException("EnemyContent._setup/_spawnObjects not found.");
				}
				List<object> list = FindMCZombiePrefabs();
				if (list.Count == 0)
				{
					throw new InvalidOperationException("Prefab 'Enemy - MCZombie' not found.");
				}
				field.SetValue(obj, setup);
				AssignSpawnObjects(field2, obj, list);
				MethodInfo? methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					return m.Name == "RegisterEnemy" && parameters.Length == 1 && parameters[0].ParameterType == enemyContentType;
				});
				if (methodInfo == null)
				{
					throw new MissingMethodException("REPOLib Enemies.RegisterEnemy(EnemyContent) not found.");
				}
				methodInfo.Invoke(null, new object[1] { obj });
				Plugin.Log.LogInfo((object)"MCZombie registered through REPOLib 4.");
			}
		}

		private static object CreateScriptableObject(Type contentType)
		{
			return (FindLoadedType("UnityEngine.ScriptableObject")?.GetMethod("CreateInstance", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Type) }, null))?.Invoke(null, new object[1] { contentType });
		}

		private static List<object> FindMCZombiePrefabs()
		{
			List<object> list = new List<object>();
			Type type = FindLoadedType("UnityEngine.AssetBundle");
			Type type2 = FindLoadedType("UnityEngine.GameObject");
			if (type == null || type2 == null)
			{
				return list;
			}
			if (!(type.GetMethod("GetAllLoadedAssetBundles", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null) is IEnumerable enumerable))
			{
				return list;
			}
			MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "LoadAllAssets" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0);
			if (methodInfo == null)
			{
				return list;
			}
			MethodInfo methodInfo2 = methodInfo.MakeGenericMethod(type2);
			PropertyInfo property = type2.GetProperty("name", BindingFlags.Instance | BindingFlags.Public);
			foreach (object item in enumerable)
			{
				if (item == null)
				{
					continue;
				}
				Array array;
				try
				{
					array = methodInfo2.Invoke(item, null) as Array;
				}
				catch
				{
					continue;
				}
				if (array == null)
				{
					continue;
				}
				foreach (object item2 in array)
				{
					if (item2 != null && ((property?.GetValue(item2, null) as string) ?? string.Empty).IndexOf("Enemy - MCZombie", StringComparison.OrdinalIgnoreCase) >= 0 && !list.Contains(item2))
					{
						list.Add(item2);
					}
				}
			}
			return list;
		}

		private static void AssignSpawnObjects(FieldInfo field, object target, List<object> prefabs)
		{
			Type fieldType = field.FieldType;
			if (!fieldType.IsGenericType || fieldType.GetGenericTypeDefinition() != typeof(List<>))
			{
				throw new InvalidOperationException("Unsupported _spawnObjects type: " + fieldType.FullName);
			}
			Type type = fieldType.GetGenericArguments()[0];
			IList list = (IList)Activator.CreateInstance(fieldType);
			foreach (object prefab in prefabs)
			{
				if (prefab != null && type.IsInstanceOfType(prefab))
				{
					list.Add(prefab);
				}
			}
			if (list.Count == 0)
			{
				throw new InvalidOperationException("No MCZombie prefab compatible with _spawnObjects.");
			}
			field.SetValue(target, list);
		}

		private static Type FindLoadedType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	internal sealed class FleshSickness : MonoBehaviour
	{
		private const byte PukeEventCode = 173;

		private const float SicknessDuration = 45f;

		private const float PukeDuration = 3f;

		private static FleshSickness _instance;

		private static GameObject _pukeTemplate;

		private static bool _templateMissingLogged;

		private static readonly HashSet<int> EatenFlesh = new HashSet<int>();

		private float _sickUntil = -1f;

		private float _nextPukeAt = -1f;

		private bool _eventSubscribed;

		internal static void Install(Harmony harmony, GameObject host)
		{
			//IL_005b: 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_007d: Expected O, but got Unknown
			//IL_007d: Expected O, but got Unknown
			_instance = host.AddComponent<FleshSickness>();
			Type type = AccessTools.TypeByName("MCZombieMod.Items.RottenFleshValuable");
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "EatFlesh", (Type[])null, (Type[])null) : null);
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"Rotten Flesh sickness unavailable: RottenFleshValuable.EatFlesh not found.");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(FleshSickness), "EatFleshPrefix", (Type[])null), new HarmonyMethod(typeof(FleshSickness), "EatFleshPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Plugin.Log.LogInfo((object)"Rotten Flesh eating guard and sickness effect installed.");
		}

		private static bool EatFleshPrefix(MonoBehaviour __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if ((Object)__instance == (Object)null)
			{
				return false;
			}
			return EatenFlesh.Add(((Object)__instance).GetInstanceID());
		}

		private static void EatFleshPostfix(GameObject player)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_004d: 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_0061: Expected O, but got Unknown
			//IL_0061: Expected O, but got Unknown
			if (Plugin.FleshSicknessEffect != null && Plugin.FleshSicknessEffect.Value && !((Object)_instance == (Object)null))
			{
				PlayerAvatar val = (((Object)player != (Object)null) ? player.GetComponent<PlayerAvatar>() : null);
				if (!((Object)val == (Object)null) && !((Object)val != (Object)PlayerAvatar.instance))
				{
					_instance.StartSickness();
				}
			}
		}

		private void StartSickness()
		{
			bool num = Time.time < _sickUntil;
			_sickUntil = Time.time + 45f;
			if (!num)
			{
				_nextPukeAt = Time.time + Random.Range(4f, 7f);
				Plugin.Log.LogInfo((object)("Rotten Flesh: local player is sick for " + 45f + "s."));
			}
		}

		private void Update()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0131: Expected O, but got Unknown
			if (!_eventSubscribed && (Object)GameManager.instance != (Object)null && SemiFunc.IsMultiplayer() && (Object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated)
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				_eventSubscribed = true;
			}
			if (_sickUntil < 0f)
			{
				return;
			}
			if (Time.time >= _sickUntil)
			{
				_sickUntil = -1f;
				_nextPukeAt = -1f;
			}
			else
			{
				if (!(_nextPukeAt > 0f) || !(Time.time >= _nextPukeAt))
				{
					return;
				}
				_nextPukeAt = Time.time + Random.Range(10f, 20f);
				PlayerAvatar instance = PlayerAvatar.instance;
				if (!((Object)instance == (Object)null))
				{
					PlayPuke(instance);
					if (SemiFunc.IsMultiplayer() && (Object)(object)instance.photonView != (Object)null)
					{
						PhotonNetwork.RaiseEvent((byte)173, (object)instance.photonView.ViewID, new RaiseEventOptions
						{
							Receivers = (ReceiverGroup)0
						}, SendOptions.SendReliable);
					}
				}
			}
		}

		private static void OnEvent(EventData data)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (data.Code == 173 && data.CustomData is int num && !((Object)_instance == (Object)null) && (Plugin.FleshSicknessEffect == null || Plugin.FleshSicknessEffect.Value))
			{
				PhotonView val = PhotonView.Find(num);
				PlayerAvatar val2 = (((Object)val != (Object)null) ? ((Component)val).GetComponent<PlayerAvatar>() : null);
				if ((Object)val2 != (Object)null)
				{
					_instance.PlayPuke(val2);
				}
			}
		}

		private void PlayPuke(PlayerAvatar avatar)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0018: 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_002c: Expected O, but got Unknown
			//IL_002c: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			GameObject pukeTemplate = GetPukeTemplate();
			if ((Object)pukeTemplate == (Object)null)
			{
				return;
			}
			Transform val = null;
			if ((Object)avatar == (Object)PlayerAvatar.instance && (Object)avatar.localCamera != (Object)null)
			{
				val = ((Component)avatar.localCamera).transform;
			}
			else if ((Object)avatar.playerAvatarVisuals != (Object)null)
			{
				val = avatar.playerAvatarVisuals.headLookAtTransform ?? ((Component)avatar.playerAvatarVisuals).transform;
			}
			if (!((Object)val == (Object)null))
			{
				GameObject val2 = Object.Instantiate<GameObject>(pukeTemplate, val);
				val2.SetActive(true);
				SemiPuke componentInChildren = val2.GetComponentInChildren<SemiPuke>(true);
				if ((Object)componentInChildren == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(PukeRoutine(val2, componentInChildren, val));
				}
			}
		}

		private static IEnumerator PukeRoutine(GameObject effect, SemiPuke puke, Transform mouth)
		{
			float timer = 0f;
			while (timer < 3f && (Object)effect != (Object)null && (Object)mouth != (Object)null)
			{
				Vector3 val = mouth.position + mouth.forward * 0.3f - mouth.up * 0.2f;
				puke.PukeActive(val, mouth.rotation);
				timer += Time.deltaTime;
				yield return null;
			}
			if ((Object)effect != (Object)null)
			{
				Object.Destroy((Object)(object)effect, 2f);
			}
		}

		private static GameObject GetPukeTemplate()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			if ((Object)_pukeTemplate != (Object)null)
			{
				return _pukeTemplate;
			}
			SemiPuke[] array = Resources.FindObjectsOfTypeAll<SemiPuke>();
			foreach (SemiPuke val in array)
			{
				if ((Object)val == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)val).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					Transform baseParticlesTransform = val.BaseParticlesTransform;
					if (!((Object)baseParticlesTransform != (Object)null) || baseParticlesTransform.IsChildOf(((Component)val).transform))
					{
						_pukeTemplate = ((Component)val).gameObject;
						Plugin.Log.LogInfo((object)("Rotten Flesh: puke effect template found: " + ((Object)_pukeTemplate).name));
						return _pukeTemplate;
					}
				}
			}
			if (!_templateMissingLogged)
			{
				_templateMissingLogged = true;
				Plugin.Log.LogWarning((object)"Rotten Flesh: no SemiPuke template found; sickness has no visual effect.");
			}
			return null;
		}
	}
	public static class LegacyCallBridge
	{
		public static void RegisterNetworkPrefabLegacyCompat(GameObject prefab)
		{
			NetworkPrefabCompat.RegisterLegacy(prefab);
		}

		public static ValuableObject GetValuableByNameCompat(string valuableName)
		{
			return ValuableCompat.GetByNameLegacy(valuableName);
		}

		public static void WarpCompat(object enemyNavMeshAgent, Vector3 position)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0149: 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)
			if (enemyNavMeshAgent == null)
			{
				return;
			}
			try
			{
				Type type = enemyNavMeshAgent.GetType();
				MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					return m.Name == "Warp" && parameters.Length == 1 && parameters[0].ParameterType == typeof(Vector3);
				});
				if (methodInfo != null)
				{
					methodInfo.Invoke(enemyNavMeshAgent, new object[1] { position });
					return;
				}
				Type type2 = type;
				while (type2 != null)
				{
					FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						if ((fieldInfo.FieldType.FullName ?? string.Empty) != "UnityEngine.AI.NavMeshAgent")
						{
							continue;
						}
						object value = fieldInfo.GetValue(enemyNavMeshAgent);
						if (value != null)
						{
							MethodInfo method = value.GetType().GetMethod("Warp", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(Vector3) }, null);
							if (!(method == null))
							{
								method.Invoke(value, new object[1] { position });
								return;
							}
						}
					}
					type2 = type2.BaseType;
				}
				Component val = (Component)((enemyNavMeshAgent is Component) ? enemyNavMeshAgent : null);
				if ((Object)val != (Object)null)
				{
					val.transform.position = position;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("MCZombie WarpCompat failed: " + ex));
				}
			}
		}

		public static GameObject SpawnNetworkPrefabLegacy(string prefabId, Vector3 position, Quaternion rotation, byte group, object[] data)
		{
			//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)
			return NetworkPrefabCompat.SpawnLegacy(prefabId, position, rotation, group, data);
		}

		public static GameObject SpawnValuableLegacy(object valuable, Vector3 position, Quaternion rotation)
		{
			//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)
			return ValuableCompat.SpawnLegacy(valuable, position, rotation);
		}

		public static void ReleaseObjectLegacy(object physGrabber, float force, object coroutineContext)
		{
			if (physGrabber == null)
			{
				return;
			}
			try
			{
				int num = TryResolvePhotonViewIdFromEatContext(coroutineContext);
				if (num <= 0)
				{
					num = TryResolveGrabbedPhotonViewId(physGrabber);
				}
				if (num <= 0)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"Rotten Flesh ReleaseObject bridge: could not resolve held item PhotonView ID.");
					}
					return;
				}
				MethodInfo method = physGrabber.GetType().GetMethod("ReleaseObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
				{
					typeof(int),
					typeof(float)
				}, null);
				if (method == null)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"Rotten Flesh ReleaseObject bridge: current ReleaseObject(int, float) was not found.");
					}
					return;
				}
				method.Invoke(physGrabber, new object[2] { num, force });
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("Rotten Flesh: legacy PhysGrabber.ReleaseObject(float) adapted to ReleaseObject(viewID=" + num + ", force=" + force + ")."));
				}
			}
			catch (TargetInvocationException ex)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("Rotten Flesh ReleaseObject bridge failed: " + (ex.InnerException ?? ex)));
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogError((object)("Rotten Flesh ReleaseObject bridge failed: " + ex2));
				}
			}
		}

		private static int TryResolvePhotonViewIdFromEatContext(object coroutineContext)
		{
			if (coroutineContext == null)
			{
				return -1;
			}
			try
			{
				object obj = coroutineContext;
				Type type = obj.GetType();
				FieldInfo field = type.GetField("<>4__this", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(obj);
					if (value != null)
					{
						obj = value;
					}
				}
				int num = TryResolvePhotonViewId(obj);
				if (num > 0)
				{
					return num;
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					string text = fieldInfo.Name ?? string.Empty;
					if (text.IndexOf("this", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("flesh", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("valuable", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						num = TryResolvePhotonViewId(fieldInfo.GetValue(coroutineContext));
						if (num > 0)
						{
							return num;
						}
					}
				}
			}
			catch
			{
			}
			return -1;
		}

		private static int TryResolveGrabbedPhotonViewId(object physGrabber)
		{
			if (physGrabber == null)
			{
				return -1;
			}
			try
			{
				Type type = physGrabber.GetType();
				while (type != null)
				{
					FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						string text = fieldInfo.Name ?? string.Empty;
						if (text.IndexOf("grab", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("held", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("object", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("target", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							object value;
							try
							{
								value = fieldInfo.GetValue(physGrabber);
							}
							catch
							{
								continue;
							}
							int num = TryResolvePhotonViewId(value);
							if (num > 0)
							{
								return num;
							}
						}
					}
					PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (PropertyInfo propertyInfo in properties)
					{
						if (propertyInfo.GetIndexParameters().Length != 0)
						{
							continue;
						}
						string text2 = propertyInfo.Name ?? string.Empty;
						if (text2.IndexOf("grab", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("held", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("object", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("target", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							object value2;
							try
							{
								value2 = propertyInfo.GetValue(physGrabber, null);
							}
							catch
							{
								continue;
							}
							int num2 = TryResolvePhotonViewId(value2);
							if (num2 > 0)
							{
								return num2;
							}
						}
					}
					type = type.BaseType;
				}
			}
			catch
			{
			}
			return -1;
		}

		private static int TryResolvePhotonViewId(object value)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			if (value == null)
			{
				return -1;
			}
			try
			{
				Type type = value.GetType();
				if ((type.FullName ?? string.Empty).IndexOf("PhotonView", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					int num = ReadViewId(value);
					if (num > 0)
					{
						return num;
					}
				}
				string[] array = new string[3] { "photonView", "PhotonView", "_photonView" };
				foreach (string name in array)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						int num2 = ReadViewId(field.GetValue(value));
						if (num2 > 0)
						{
							return num2;
						}
					}
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.GetIndexParameters().Length == 0)
					{
						int num3 = ReadViewId(property.GetValue(value, null));
						if (num3 > 0)
						{
							return num3;
						}
					}
				}
				Component val = (Component)((value is Component) ? value : null);
				GameObject val2 = (GameObject)((value is GameObject) ? value : null);
				if ((Object)val != (Object)null)
				{
					val2 = val.gameObject;
				}
				if ((Object)val2 != (Object)null)
				{
					Component[] components = val2.GetComponents<Component>();
					foreach (Component val3 in components)
					{
						if (!((Object)val3 == (Object)null) && (((object)val3).GetType().FullName ?? string.Empty).IndexOf("PhotonView", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							int num4 = ReadViewId(val3);
							if (num4 > 0)
							{
								return num4;
							}
						}
					}
				}
				array = new string[6] { "gameObject", "GameObject", "transform", "Transform", "physGrabObject", "PhysGrabObject" };
				foreach (string name2 in array)
				{
					FieldInfo field2 = type.GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null)
					{
						object value2 = field2.GetValue(value);
						if (value2 != value)
						{
							int num5 = TryResolvePhotonViewId(value2);
							if (num5 > 0)
							{
								return num5;
							}
						}
					}
					PropertyInfo property2 = type.GetProperty(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(property2 != null) || property2.GetIndexParameters().Length != 0)
					{
						continue;
					}
					object value3 = property2.GetValue(value, null);
					if (value3 != value)
					{
						int num6 = TryResolvePhotonViewId(value3);
						if (num6 > 0)
						{
							return num6;
						}
					}
				}
			}
			catch
			{
			}
			return -1;
		}

		private static int ReadViewId(object photonView)
		{
			if (photonView == null)
			{
				return -1;
			}
			try
			{
				Type type = photonView.GetType();
				PropertyInfo property = type.GetProperty("ViewID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.GetIndexParameters().Length == 0)
				{
					object value = property.GetValue(photonView, null);
					if (value != null)
					{
						return Convert.ToInt32(value);
					}
				}
				FieldInfo field = type.GetField("ViewID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value2 = field.GetValue(photonView);
					if (value2 != null)
					{
						return Convert.ToInt32(value2);
					}
				}
			}
			catch
			{
			}
			return -1;
		}
	}
	internal static class LegacyEnemyLookupCompat
	{
		internal static void Install(Harmony harmony)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = (AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.Enemies", throwOnError: false))?.GetMethod("GetEnemyByName", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				MethodInfo method = typeof(LegacyEnemyLookupCompat).GetMethod("GetEnemyByNamePrefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo == null || method == null)
				{
					Plugin.Log.LogWarning((object)"MCZombie legacy GetEnemyByName bridge could not be installed.");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"MCZombie legacy GetEnemyByName bridge installed.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("MCZombie legacy GetEnemyByName bridge failed: " + ex));
			}
		}

		private static bool GetEnemyByNamePrefix(string name, ref EnemySetup __result)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (string.IsNullOrEmpty(name))
			{
				return true;
			}
			if (name.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return true;
			}
			object lastMCZombieSetup = EnemyRegistration.LastMCZombieSetup;
			EnemySetup val = (EnemySetup)((lastMCZombieSetup is EnemySetup) ? lastMCZombieSetup : null);
			if ((Object)val == (Object)null)
			{
				val = TryFindModernMCZombieSetup();
			}
			if ((Object)val == (Object)null)
			{
				return true;
			}
			__result = val;
			Plugin.Log.LogInfo((object)("MCZombie legacy GetEnemyByName redirected to modern EnemySetup | requested='" + name + "'."));
			return false;
		}

		private static EnemySetup TryFindModernMCZombieSetup()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			try
			{
				Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.Enemies", throwOnError: false);
				if (type == null)
				{
					return null;
				}
				string[] array = new string[2] { "AllEnemies", "RegisteredEnemies" };
				foreach (string name in array)
				{
					if (!(type.GetProperty(name, BindingFlags.Static | BindingFlags.Public)?.GetValue(null, null) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						EnemySetup val = ResolveEnemySetup(item);
						if (!((Object)val == (Object)null))
						{
							string text = ((Object)val).name ?? string.Empty;
							if (text.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) >= 0)
							{
								return val;
							}
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static EnemySetup ResolveEnemySetup(object value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			if (value == null)
			{
				return null;
			}
			EnemySetup val = (EnemySetup)((value is EnemySetup) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Type type = value.GetType();
			string[] array = new string[5] { "_setup", "setup", "Setup", "enemySetup", "EnemySetup" };
			foreach (string name in array)
			{
				try
				{
					object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(value);
					EnemySetup val2 = (EnemySetup)((obj is EnemySetup) ? obj : null);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.GetIndexParameters().Length == 0)
					{
						object value2 = property.GetValue(value, null);
						EnemySetup val3 = (EnemySetup)((value2 is EnemySetup) ? value2 : null);
						if ((Object)(object)val3 != (Object)null)
						{
							return val3;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}
	internal static class MCZombieAwakeCompat
	{
		internal static bool Prefix(object __instance)
		{
			if (__instance == null)
			{
				Plugin.Log.LogError((object)"MCZombie Awake prefix received null instance.");
				return false;
			}
			try
			{
				Type type = __instance.GetType();
				Plugin.Log.LogInfo((object)"Running clean MCZombieMod.Awake compatibility path.");
				SetStaticMember(type, "Instance", __instance);
				SetupMCZombieConfig(__instance, type);
				DetachTransform(__instance);
				InvokeNoArgs(__instance, type, "LoadAssetBundle");
				RegisterEnemiesFromLoadedBundle(__instance, type);
				NetworkPrefabCompat.CacheAndRegisterFromMCZombieBundle(GetAssetBundle(__instance, type));
				InvokeNoArgs(__instance, type, "FixAllPrefabAudioMixerGroups", optional: true);
				SetupOriginalHarmony(__instance, type);
				InvokeNoArgs(__instance, type, "Patch", optional: true);
				Plugin.Log.LogInfo((object)"MCZombieMod initialized through MCZombieFix 1.1.0.");
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("MCZombie compatible Awake failed: " + Unwrap(ex)));
				return false;
			}
		}

		private static void SetupMCZombieConfig(object instance, Type pluginType)
		{
			Type type = pluginType.Assembly.GetType("MCZombieMod.MCZombieConfig", throwOnError: false);
			if (type == null)
			{
				Plugin.Log.LogWarning((object)"MCZombieConfig type not found.");
				return;
			}
			object configFile = FindBepInExConfigFile(instance, pluginType);
			ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Plugin.Log.LogInfo((object)("MCZombieConfig constructors: " + string.Join(" | ", constructors.Select(DescribeConstructor).ToArray())));
			object obj = null;
			foreach (ConstructorInfo item in constructors.OrderBy((ConstructorInfo c) => c.GetParameters().Length))
			{
				object[] array = BuildConstructorArguments(item.GetParameters(), instance, configFile);
				if (array == null)
				{
					continue;
				}
				try
				{
					obj = item.Invoke(array);
					if (obj != null)
					{
						break;
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("MCZombieConfig constructor failed: " + DescribeConstructor(item) + " | " + Unwrap(ex).Message));
				}
			}
			if (obj == null)
			{
				try
				{
					obj = FormatterServices.GetUninitializedObject(type);
					Plugin.Log.LogWarning((object)"MCZombieConfig created without constructor as fallback.");
				}
				catch
				{
					obj = null;
				}
			}
			if (obj == null)
			{
				Plugin.Log.LogWarning((object)"Could not construct MCZombieConfig.");
			}
			else if (AssignMCZombieConfig(pluginType, instance, type, obj))
			{
				Plugin.Log.LogInfo((object)"MCZombieConfig initialized and assigned.");
			}
			else
			{
				Plugin.Log.LogWarning((object)"MCZombieConfig object created but no compatible storage member was found.");
			}
		}

		private static bool AssignMCZombieConfig(Type pluginType, object instance, Type configType, object mcConfig)
		{
			BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = pluginType.GetField("Config", bindingFlags);
			if (field != null && field.FieldType.IsAssignableFrom(configType))
			{
				field.SetValue(null, mcConfig);
				Plugin.Log.LogInfo((object)("MCZombieConfig assigned to static field: " + pluginType.FullName + "." + field.Name));
				return true;
			}
			PropertyInfo property = pluginType.GetProperty("Config", bindingFlags);
			if (property != null && property.CanWrite && property.PropertyType.IsAssignableFrom(configType))
			{
				property.SetValue(null, mcConfig, null);
				Plugin.Log.LogInfo((object)("MCZombieConfig assigned to static property: " + pluginType.FullName + "." + property.Name));
				return true;
			}
			FieldInfo[] fields = pluginType.GetFields(bindingFlags);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType == configType || fieldInfo.FieldType.IsAssignableFrom(configType))
				{
					fieldInfo.SetValue(null, mcConfig);
					Plugin.Log.LogInfo((object)("MCZombieConfig assigned by type to static field: " + pluginType.FullName + "." + fieldInfo.Name));
					return true;
				}
			}
			PropertyInfo[] properties = pluginType.GetProperties(bindingFlags);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanWrite && (propertyInfo.PropertyType == configType || propertyInfo.PropertyType.IsAssignableFrom(configType)))
				{
					propertyInfo.SetValue(null, mcConfig, null);
					Plugin.Log.LogInfo((object)("MCZombieConfig assigned by type to static property: " + pluginType.FullName + "." + propertyInfo.Name));
					return true;
				}
			}
			fields = pluginType.GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo2 in fields)
			{
				if (fieldInfo2.FieldType == configType || fieldInfo2.FieldType.IsAssignableFrom(configType))
				{
					fieldInfo2.SetValue(instance, mcConfig);
					Plugin.Log.LogInfo((object)("MCZombieConfig assigned by type to instance field: " + pluginType.FullName + "." + fieldInfo2.Name));
					return true;
				}
			}
			properties = pluginType.GetProperties(bindingAttr);
			foreach (PropertyInfo propertyInfo2 in properties)
			{
				if (propertyInfo2.CanWrite && (propertyInfo2.PropertyType == configType || propertyInfo2.PropertyType.IsAssignableFrom(configType)))
				{
					propertyInfo2.SetValue(instance, mcConfig, null);
					Plugin.Log.LogInfo((object)("MCZombieConfig assigned by type to instance property: " + pluginType.FullName + "." + propertyInfo2.Name));
					return true;
				}
			}
			string text = string.Join(" | ", (from f in pluginType.GetFields(bindingFlags | BindingFlags.Instance)
				select (f.IsStatic ? "static " : "instance ") + f.FieldType.FullName + " " + f.Name).ToArray());
			string text2 = string.Join(" | ", (from prop in pluginType.GetProperties(bindingFlags | BindingFlags.Instance)
				select prop.PropertyType.FullName + " " + prop.Name + " [write=" + prop.CanWrite + "]").ToArray());
			Plugin.Log.LogWarning((object)("MCZombie storage diagnostics | fields: " + text));
			Plugin.Log.LogWarning((object)("MCZombie storage diagnostics | properties: " + text2));
			return false;
		}

		private static object FindBepInExConfigFile(object instance, Type type)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty("Config", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && typeof(ConfigFile).IsAssignableFrom(property.PropertyType))
				{
					try
					{
						object value = property.GetValue(instance, null);
						if (value != null)
						{
							Plugin.Log.LogInfo((object)("BepInEx ConfigFile resolved from " + type2.FullName + ".Config."));
							return value;
						}
					}
					catch
					{
					}
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static object[] BuildConstructorArguments(ParameterInfo[] parameters, object mcZombiePlugin, object configFile)
		{
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				Type parameterType = parameterInfo.ParameterType;
				if (configFile != null && parameterType.IsInstanceOfType(configFile))
				{
					array[i] = configFile;
					continue;
				}
				if (mcZombiePlugin != null && parameterType.IsInstanceOfType(mcZombiePlugin))
				{
					array[i] = mcZombiePlugin;
					continue;
				}
				if (typeof(ManualLogSource).IsAssignableFrom(parameterType))
				{
					array[i] = Plugin.Log;
					continue;
				}
				if (parameterInfo.HasDefaultValue)
				{
					array[i] = parameterInfo.DefaultValue;
					continue;
				}
				if (!parameterType.IsValueType)
				{
					array[i] = null;
					continue;
				}
				try
				{
					array[i] = Activator.CreateInstance(parameterType);
				}
				catch
				{
					return null;
				}
			}
			return array;
		}

		private static string DescribeConstructor(ConstructorInfo ctor)
		{
			return ".ctor(" + string.Join(", ", (from p in ctor.GetParameters()
				select p.ParameterType.FullName + " " + p.Name).ToArray()) + ")";
		}

		private static object GetAssetBundle(object instance, Type pluginType)
		{
			return pluginType.GetField("_assetBundle", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) ?? throw new InvalidOperationException("MCZombie _assetBundle is null after LoadAssetBundle().");
		}

		private static void RegisterEnemiesFromLoadedBundle(object instance, Type pluginType)
		{
			object assetBundle = GetAssetBundle(instance, pluginType);
			Type type = FindLoadedType("EnemySetup");
			if (type == null)
			{
				throw new MissingMemberException("EnemySetup game type not found.");
			}
			MethodInfo? methodInfo = assetBundle.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "LoadAllAssets" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0);
			if (methodInfo == null)
			{
				throw new MissingMethodException("AssetBundle.LoadAllAssets<T>() not found.");
			}
			if (!(methodInfo.MakeGenericMethod(type).Invoke(assetBundle, null) is Array { Length: not 0 } array))
			{
				throw new InvalidOperationException("No EnemySetup found in MCZombie asset bundle.");
			}
			int num = 0;
			foreach (object item in array)
			{
				if (item != null)
				{
					EnemyRegistration.RegisterEnemy(item);
					num++;
				}
			}
			Plugin.Log.LogInfo((object)("MCZombie EnemySetup assets processed: " + num));
		}

		private static void DetachTransform(object instance)
		{
			object obj = instance.GetType().GetProperty("transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance, null);
			obj?.GetType().GetProperty("parent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, null, null);
		}

		private static void SetupOriginalHarmony(object instance, Type pluginType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Harmony value = new Harmony("MCZombieMod.compat.original");
			if (!SetMember(instance, pluginType, "Harmony", value))
			{
				Plugin.Log.LogWarning((object)"MCZombie Harmony member not found; Patch() will still be attempted.");
			}
		}

		private static void InvokeNoArgs(object instance, Type type, string methodName, bool optional = false)
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				if (!optional)
				{
					throw new MissingMethodException(type.FullName, methodName);
				}
				Plugin.Log.LogWarning((object)(methodName + "() not found; skipped."));
			}
			else
			{
				method.Invoke(instance, null);
			}
		}

		private static bool SetMember(object instance, Type type, string name, object value)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && (value == null || field.FieldType.IsInstanceOfType(value)))
			{
				field.SetValue(instance, value);
				return true;
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite && (value == null || property.PropertyType.IsInstanceOfType(value)))
			{
				property.SetValue(instance, value, null);
				return true;
			}
			return false;
		}

		private static bool SetStaticMember(Type type, string name, object value)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(null, value);
				return true;
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				property.SetValue(null, value, null);
				return true;
			}
			return false;
		}

		private static Type FindLoadedType(string simpleOrFullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(simpleOrFullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
				try
				{
					Type type2 = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == simpleOrFullName);
					if (type2 != null)
					{
						return type2;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static Exception Unwrap(Exception ex)
		{
			while (ex is TargetInvocationException && ex.InnerException != null)
			{
				ex = ex.InnerException;
			}
			return ex;
		}
	}
	internal static class MinecraftSpawnGuarantee
	{
		private static string _trackedLevel = string.Empty;

		private static float _levelSeenAt = -1f;

		private static bool _doneForLevel;

		private static object _pendingVictim;

		private static float _pendingAt;

		private const int MaxReplacementAttempts = 5;

		private static int _replacementAttempts;

		private static int _cachedZombieDifficulty = int.MinValue;

		internal static IEnumerator Loop()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(2f);
				try
				{
					if (Plugin.GuaranteeMinecraftZombie == null || !Plugin.GuaranteeMinecraftZombie.Value)
					{
						continue;
					}
					string currentLevelName = GetCurrentLevelName();
					if (!IsMinecraftLevelName(currentLevelName))
					{
						ResetLevelState();
					}
					else
					{
						if (!IsHostOrSingleplayer() || EnemyRegistration.LastMCZombieSetup == null)
						{
							continue;
						}
						if (!string.Equals(_trackedLevel, currentLevelName, StringComparison.OrdinalIgnoreCase))
						{
							_trackedLevel = currentLevelName;
							_levelSeenAt = Time.realtimeSinceStartup;
							_doneForLevel = false;
							_pendingVictim = null;
							_pendingAt = 0f;
							_replacementAttempts = 0;
							Plugin.Log.LogInfo((object)("Minecraft level detected: '" + currentLevelName + "'. Waiting for normal enemy spawn selection."));
						}
						else
						{
							if (_doneForLevel || _levelSeenAt < 0f || Time.realtimeSinceStartup - _levelSeenAt < 10f)
							{
								continue;
							}
							int num = CountActiveMCZombies();
							if (num > 0)
							{
								if (_pendingVictim != null)
								{
									string enemyName = GetEnemyName(_pendingVictim);
									RemoveEnemyFromDirector(_pendingVictim);
									DestroyEnemyNetworkSafe(_pendingVictim);
									Plugin.Log.LogInfo((object)("MCZombie LIVE QUOTA REPLACE complete | replaced='" + enemyName + "' | zombieCount=" + num + " | level='" + currentLevelName + "'"));
								}
								else
								{
									Plugin.Log.LogInfo((object)("MCZombie LIVE QUOTA OK | zombie already active naturally | count=" + num + " | level='" + currentLevelName + "'"));
								}
								_pendingVictim = null;
								_doneForLevel = true;
							}
							else if (_pendingVictim != null)
							{
								if (Time.realtimeSinceStartup - _pendingAt > 6f)
								{
									Plugin.Log.LogWarning((object)"MCZombie LIVE QUOTA: spawned zombie was not confirmed after 6s; original enemy kept.");
									_pendingVictim = null;
									_pendingAt = 0f;
								}
							}
							else if (++_replacementAttempts > 5)
							{
								_doneForLevel = true;
								Plugin.Log.LogWarning((object)("MCZombie LIVE QUOTA: no replacement after " + 5 + " attempts; giving up for '" + currentLevelName + "'."));
							}
							else
							{
								BeginReplacement(currentLevelName);
							}
						}
						continue;
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("MCZombie Minecraft quota replacement failed: " + Unwrap(ex)));
				}
			}
		}

		private static void BeginReplacement(string level)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_019e: 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_01a8: 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)
			//IL_01b6: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0110: 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)
			if (EnemyRegistration.LastMCZombieSetup == null)
			{
				return;
			}
			if (!TryGetZombieDifficulty(out var difficulty))
			{
				Plugin.Log.LogWarning((object)"MCZombie LIVE QUOTA: zombie difficulty unavailable; waiting.");
				return;
			}
			Type type = FindLoadedType("EnemyParent");
			if (type == null)
			{
				return;
			}
			Object[] array = Object.FindObjectsOfType(type);
			if (array == null || array.Length == 0)
			{
				return;
			}
			Transform val = FindAnyPlayerTransform();
			object obj = null;
			float num = -1f;
			Object[] array2 = array;
			foreach (Object val2 in array2)
			{
				Component val3 = (Component)((val2 is Component) ? val2 : null);
				if (!((Object)val3 == (Object)null) && !((Object)val3.gameObject == (Object)null) && val3.gameObject.activeInHierarchy && !IsZombieName(GetEnemyName(val2)) && !IsZombieName(((Object)val3).name) && !IsZombieName(((Object)val3.gameObject).name) && TryReadInt(val2, "difficulty", out var value) && value == difficulty)
				{
					float num2 = (((Object)val != (Object)null) ? Vector3.Distance(val.position, val3.transform.position) : 0f);
					if (obj == null || num2 > num)
					{
						obj = val2;
						num = num2;
					}
				}
			}
			if (obj == null)
			{
				Plugin.Log.LogWarning((object)("MCZombie LIVE QUOTA: no active enemy of zombie tier " + difficulty + " available to replace without changing the tier quota."));
				return;
			}
			Component val4 = (Component)((obj is Component) ? obj : null);
			if (!((Object)val4 == (Object)null))
			{
				Vector3 val5 = SnapToLevelPoint(val4.transform.position);
				Quaternion rotation = val4.transform.rotation;
				string enemyName = GetEnemyName(obj);
				if (!SpawnMCZombie(val5, rotation))
				{
					Plugin.Log.LogWarning((object)"MCZombie LIVE QUOTA: modern zombie spawn failed; original enemy kept.");
					return;
				}
				_pendingVictim = obj;
				_pendingAt = Time.realtimeSinceStartup;
				Plugin.Log.LogInfo((object)("MCZombie LIVE QUOTA REPLACE pending | replace='" + enemyName + "' | tier=" + difficulty + " | spawnAt=" + Vec(val5) + " | level='" + level + "'"));
			}
		}

		private static bool SpawnMCZombie(Vector3 position, Quaternion rotation)
		{
			//IL_009c: 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)
			try
			{
				object setup = EnemyRegistration.LastMCZombieSetup;
				if (setup == null)
				{
					return false;
				}
				Type type = FindAssembly("REPOLib")?.GetType("REPOLib.Modules.Enemies", throwOnError: false);
				if (type == null)
				{
					return false;
				}
				MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					if (m.Name != "SpawnEnemy")
					{
						return false;
					}
					ParameterInfo[] parameters = m.GetParameters();
					return parameters.Length == 4 && parameters[0].ParameterType.IsInstanceOfType(setup) && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion) && parameters[3].ParameterType == typeof(bool);
				});
				if (methodInfo == null)
				{
					Plugin.Log.LogWarning((object)"REPOLib Enemies.SpawnEnemy(EnemySetup, Vector3, Quaternion, bool) not found.");
					return false;
				}
				object obj = methodInfo.Invoke(null, new object[4] { setup, position, rotation, false });
				if (!(obj is IEnumerable enumerable))
				{
					return obj != null;
				}
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						return true;
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("MCZombie modern spawn failed: " + Unwrap(ex)));
				return false;
			}
		}

		private static bool TryGetZombieDifficulty(out int difficulty)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			difficulty = -1;
			if (_cachedZombieDifficulty != int.MinValue)
			{
				difficulty = _cachedZombieDifficulty;
				return true;
			}
			Type type = FindLoadedType("EnemyParent");
			if (type == null)
			{
				return false;
			}
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			if (array == null)
			{
				return false;
			}
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if ((Object)val == (Object)null || string.IsNullOrEmpty(((Object)val).name) || ((Object)val).name.IndexOf("Enemy - MCZombie", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				Component[] componentsInChildren = val.GetComponentsInChildren(type, true);
				if (componentsInChildren == null)
				{
					continue;
				}
				Component[] array3 = componentsInChildren;
				foreach (Component val2 in array3)
				{
					if ((Object)val2 != (Object)null && TryReadInt(val2, "difficulty", out difficulty))
					{
						_cachedZombieDifficulty = difficulty;
						return true;
					}
				}
			}
			return false;
		}

		private static int CountActiveMCZombies()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			Type type = FindLoadedType("EnemyParent");
			if (type == null)
			{
				return 0;
			}
			Object[] array = Object.FindObjectsOfType(type);
			if (array == null)
			{
				return 0;
			}
			int num = 0;
			Object[] array2 = array;
			foreach (Object val in array2)
			{
				Component val2 = (Component)((val is Component) ? val : null);
				if (!((Object)val2 == (Object)null) && !((Object)val2.gameObject == (Object)null) && val2.gameObject.activeInHierarchy && (IsZombieName(GetEnemyName(val)) || IsZombieName(((Object)val2).name) || IsZombieName(((Object)val2.gameObject).name)))
				{
					num++;
				}
			}
			return num;
		}

		private static bool IsZombieName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			if (value.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) < 0 && value.IndexOf("MC Zombie", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return value.IndexOf("Enemy - MCZombie", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static string GetEnemyName(object enemyParent)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			string text = GetMemberValue(enemyParent, "enemyName") as string;
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			Component val = (Component)((enemyParent is Component) ? enemyParent : null);
			if ((Object)val != (Object)null)
			{
				object obj = ((Object)val).name;
				if (obj == null)
				{
					GameObject gameObject = val.gameObject;
					obj = (((Object)(object)gameObject != (Object)null) ? ((Object)gameObject).name : null) ?? "<unknown>";
				}
				return (string)obj;
			}
			return "<unknown>";
		}

		private static void RemoveEnemyFromDirector(object parent)
		{
			if (parent == null)
			{
				return;
			}
			try
			{
				Type type = FindLoadedType("EnemyDirector");
				if (!(type == null))
				{
					Object val = Object.FindObjectOfType(type);
					if (!(val == (Object)null) && GetMemberValue(val, "enemiesSpawned") is IList list && list.Contains(parent))
					{
						list.Remove(parent);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not remove replaced enemy from EnemyDirector list: " + Unwrap(ex).Message));
			}
		}

		private static void DestroyEnemyNetworkSafe(object parent)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Component val = (Component)((parent is Component) ? parent : null);
			if ((Object)val == (Object)null || (Object)val.gameObject == (Object)null)
			{
				return;
			}
			GameObject gameObject = val.gameObject;
			try
			{
				MethodInfo methodInfo = (FindAssembly("PhotonUnityNetworking")?.GetType("Photon.Pun.PhotonNetwork", throwOnError: false))?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					return m.Name == "Destroy" && parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject);
				});
				if (methodInfo != null)
				{
					methodInfo.Invoke(null, new object[1] { gameObject });
					return;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Photon destroy failed; using Unity Destroy: " + Unwrap(ex).Message));
			}
			Object.Destroy((Object)gameObject);
		}

		private static bool IsHostOrSingleplayer()
		{
			try
			{
				Type type = FindAssembly("PhotonUnityNetworking")?.GetType("Photon.Pun.PhotonNetwork", throwOnError: false);
				if (type == null)
				{
					return true;
				}
				PropertyInfo property = type.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public);
				if (!(property != null) || !Convert.ToBoolean(property.GetValue(null, null)))
				{
					return true;
				}
				PropertyInfo property2 = type.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public);
				return property2 != null && Convert.ToBoolean(property2.GetValue(null, null));
			}
			catch
			{
				return true;
			}
		}

		private static string GetCurrentLevelName()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			try
			{
				Type type = FindLoadedType("RunManager");
				if (type != null)
				{
					object obj = GetStaticMemberValue(type, "instance") ?? GetStaticMemberValue(type, "Instance");
					if (obj != null)
					{
						object obj2 = GetMemberValue(obj, "levelCurrent") ?? GetMemberValue(obj, "LevelCurrent");
						if (obj2 != null)
						{
							Object val = (Object)((obj2 is Object) ? obj2 : null);
							if (val != (Object)null && !string.IsNullOrEmpty(val.name))
							{
								return val.name;
							}
							string[] array = new string[4] { "name", "Name", "levelName", "LevelName" };
							foreach (string name in array)
							{
								string text = GetMemberValue(obj2, name) as string;
								if (!string.IsNullOrEmpty(text))
								{
									return text;
								}
							}
						}
					}
				}
			}
			catch
			{
			}
			return string.Empty;
		}

		private static bool IsMinecraftLevelName(string levelName)
		{
			if (string.IsNullOrEmpty(levelName))
			{
				return false;
			}
			if (levelName.IndexOf("Minecraft Village", StringComparison.OrdinalIgnoreCase) < 0 && levelName.IndexOf("Minecraft Cave", StringComparison.OrdinalIgnoreCase) < 0 && levelName.IndexOf("Minecraft Stronghold", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return levelName.IndexOf("Stronghold", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static Transform FindAnyPlayerTransform()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = FindLoadedType("PlayerAvatar");
				if (type == null)
				{
					return null;
				}
				Object[] array = Object.FindObjectsOfType(type);
				if (array == null || array.Length == 0)
				{
					return null;
				}
				Object[] array2 = array;
				foreach (Object val in array2)
				{
					Component val2 = (Component)((val is Component) ? val : null);
					if (!((Object)val2 == (Object)null) && !((Object)val2.gameObject == (Object)null) && val2.gameObject.activeInHierarchy)
					{
						object obj = GetMemberValue(val2, "isLocal") ?? GetMemberValue(val2, "isLocalPlayer");
						if (obj is bool && (bool)obj)
						{
							return val2.transform;
						}
					}
				}
				Object val3 = array[0];
				Object val4 = ((val3 is Component) ? val3 : null);
				return (val4 != (Object)null) ? ((Component)val4).transform : null;
			}
			catch
			{
				return null;
			}
		}

		private static bool TryReadInt(object target, string name, out int value)
		{
			value = -1;
			try
			{
				object memberValue = GetMemberValue(target, name);
				if (memberValue == null)
				{
					return false;
				}
				value = Convert.ToInt32(memberValue);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static object GetMemberValue(object target, string name)
		{
			if (target == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			Type type = target.GetType();
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = type.GetField(name, bindingAttr);
			if (field != null)
			{
				try
				{
					return field.GetValue(target);
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(name, bindingAttr);
			if (property != null && property.CanRead)
			{
				try
				{
					return property.GetValue(target, null);
				}
				catch
				{
				}
			}
			return null;
		}

		private static object GetStaticMemberValue(Type type, string name)
		{
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = type.GetField(name, bindingAttr);
			if (field != null)
			{
				try
				{
					return field.GetValue(null);
				}
				catch
				{
				}
			}
			PropertyInfo property = type.GetProperty(name, bindingAttr);
			if (property != null && property.CanRead)
			{
				try
				{
					return property.GetValue(null, null);
				}
				catch
				{
				}
			}
			return null;
		}

		private static Type FindLoadedType(string simpleOrFullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(simpleOrFullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
				try
				{
					Type type2 = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == simpleOrFullName);
					if (type2 != null)
					{
						return type2;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static Assembly FindAssembly(string name)
		{
			return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, name, StringComparison.OrdinalIgnoreCase));
		}

		private static Exception Unwrap(Exception ex)
		{
			while (ex is TargetInvocationException && ex.InnerException != null)
			{
				ex = ex.InnerException;
			}
			return ex;
		}

		private static string Vec(Vector3 v)
		{
			return "(" + v.x.ToString("0.00") + "," + v.y.ToString("0.00") + "," + v.z.ToString("0.00") + ")";
		}

		private static void ResetLevelState()
		{
			_trackedLevel = string.Empty;
			_levelSeenAt = -1f;
			_doneForLevel = false;
			_pendingVictim = null;
			_pendingAt = 0f;
			_replacementAttempts = 0;
		}

		private static Vector3 SnapToLevelPoint(Vector3 position)
		{
			//IL_009f: 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_0029: Expected O, but got Unknown
			//IL_002b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//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_00a1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				LevelPoint val = null;
				float num = float.MaxValue;
				foreach (LevelPoint item in SemiFunc.LevelPointsGetAll())
				{
					if (!((Object)item == (Object)null))
					{
						float num2 = Vector3.Distance(position, ((Component)item).transform.position);
						if (num2 < num)
						{
							val = item;
							num = num2;
						}
					}
				}
				if ((Object)val != (Object)null)
				{
					return ((Component)val).transform.position;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("MCZombie LIVE QUOTA: level point lookup failed, using enemy position: " + ex.Message));
			}
			return position;
		}
	}
	internal static class NetworkPrefabCompat
	{
		private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		internal static void CacheAndRegisterFromMCZombieBundle(object bundle)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			if (bundle == null)
			{
				return;
			}
			MethodInfo methodInfo = bundle.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "LoadAllAssets" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0);
			if (methodInfo == null || !(methodInfo.MakeGenericMethod(typeof(GameObject)).Invoke(bundle, null) is Array array))
			{
				return;
			}
			int num = 0;
			foreach (GameObject item in array)
			{
				GameObject val = item;
				if (!((Object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.IndexOf("Rotten Flesh", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					CachePrefab(val);
					TryRegisterModern(val);
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)("Rotten Flesh network prefab(s) cached: " + num));
			}
			else
			{
				Plugin.Log.LogWarning((object)"No Rotten Flesh GameObject found in MCZombie asset bundle.");
			}
		}

		internal static GameObject Find(string prefabId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			if (string.IsNullOrEmpty(prefabId))
			{
				return null;
			}
			if (Cache.TryGetValue(prefabId, out var value) && (Object)value != (Object)null)
			{
				return value;
			}
			string text = Normalize(prefabId);
			foreach (KeyValuePair<string, GameObject> item in Cache)
			{
				if ((Object)item.Value != (Object)null && Normalize(item.Key) == text)
				{
					return item.Value;
				}
			}
			return null;
		}

		internal static GameObject SpawnLegacy(string prefabId, Vector3 position, Quaternion rotation, byte group, object[] data)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_0154: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			try
			{
				Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false);
				if (type == null)
				{
					throw new MissingMemberException("REPOLib.Modules.NetworkPrefabs not found.");
				}
				MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					ParameterInfo[] parameters = m.GetParameters();
					return m.Name == "GetNetworkPrefabRef" && parameters.Length == 1 && parameters[0].ParameterType == typeof(string);
				});
				object obj = null;
				if (methodInfo != null)
				{
					try
					{
						obj = methodInfo.Invoke(null, new object[1] { prefabId });
					}
					catch
					{
					}
				}
				if (obj == null)
				{
					GameObject val = Find(prefabId);
					if ((Object)val != (Object)null)
					{
						TryRegisterModern(val);
						if (methodInfo != null)
						{
							try
							{
								obj = methodInfo.Invoke(null, new object[1] { prefabId });
							}
							catch
							{
							}
						}
					}
				}
				MethodInfo methodInfo2 = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
				{
					if (m.Name != "SpawnNetworkPrefab")
					{
						return false;
					}
					ParameterInfo[] parameters = m.GetParameters();
					return parameters.Length == 5 && parameters[0].ParameterType.Name.IndexOf("PrefabRef", StringComparison.OrdinalIgnoreCase) >= 0 && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion) && parameters[3].ParameterType == typeof(byte) && parameters[4].ParameterType == typeof(object[]);
				});
				if (methodInfo2 == null)
				{
					throw new MissingMethodException("Modern SpawnNetworkPrefab(PrefabRef, Vector3, Quaternion, byte, object[]) not found.");
				}
				if (obj == null)
				{
					Plugin.Log.LogWarning((object)("PaintedUtils: network prefab ID not resolvable: " + prefabId));
					return null;
				}
				object obj4 = methodInfo2.Invoke(null, new object[5] { obj, position, rotation, group, data });
				object obj5 = ((obj4 is GameObject) ? obj4 : null);
				Plugin.Log.LogInfo((object)("PaintedUtils: legacy SpawnNetworkPrefab adapted for '" + prefabId + "'."));
				return (GameObject)obj5;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("PaintedUtils SpawnNetworkPrefab compatibility failed: " + ex));
				return null;
			}
		}

		private static void CachePrefab(GameObject prefab)
		{
			Cache[((Object)prefab).name] = prefab;
			if (((Object)prefab).name.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
			{
				string text = ((Object)prefab).name.Substring(0, ((Object)prefab).name.Length - "(Clone)".Length).Trim();
				if (!string.IsNullOrEmpty(text))
				{
					Cache[text] = prefab;
				}
			}
		}

		internal static void RegisterLegacy(GameObject prefab)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if (!((Object)prefab == (Object)null))
			{
				CachePrefab(prefab);
				TryRegisterModern(prefab);
			}
		}

		private static void TryRegisterModern(GameObject prefab)
		{
			try
			{
				Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false);
				if (!(type == null))
				{
					MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m)
					{
						ParameterInfo[] parameters = m.GetParameters();
						return m.Name == "RegisterNetworkPrefab" && parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject);
					});
					if (methodInfo != null)
					{
						methodInfo.Invoke(null, new object[1] { prefab });
						Plugin.Log.LogInfo((object)"Rotten Flesh registered through modern NetworkPrefabs runtime API.");
					}
					else
					{
						Plugin.Log.LogInfo((object)"Rotten Flesh cached for compatibility; no direct GameObject registration overload found.");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Rotten Flesh network registration warning: " + ex.Message));
			}
		}

		private static string Normalize(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			string text = value.Trim();
			if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(0, text.Length - 7).Trim();
			}
			return new string(text.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray());
		}
	}
	internal static class PaintedUtilsCompat
	{
		internal static bool SkipLegacyPatchAll()
		{
			Plugin.Log.LogInfo((object)"Skipped PaintedUtils legacy Harmony PatchAll incompatible with REPOLib 4.");
			return false;
		}
	}
	[BepInPlugin("000.CaptainTeam.MCZombieFix", "MCZombie Fix", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony _harmony;

		internal static ConfigEntry<bool> GuaranteeMinecraftZombie;

		internal static ConfigEntry<bool> FleshSicknessEffect;

		private void Awake()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MCZombieFix 1.1.0 loaded.");
			GuaranteeMinecraftZombie = ((BaseUnityPlugin)this).Config.Bind<bool>("MCZombie Compatibility", "Guarantee Zombie On Minecraft Maps", true, "Guarantees one MCZombie on Minecraft Village, Cave and Stronghold by replacing one active enemy of the same difficulty tier.");
			FleshSicknessEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("Rotten Flesh", "Sickness Effect", true, "After eating Rotten Flesh the player gets sick for a while and pukes a few times (game's own puke effect, visible to everyone).");
			_harmony = new Harmony("000.CaptainTeam.MCZombieFix.runtime");
			InstallPaintedUtilsPatchGuard();
			InstallMCZombieAwakePatch();
			LegacyEnemyLookupCompat.Install(_harmony);
			FleshSickness.Install(_harmony, ((Component)this).gameObject);
			ZombieGrabFix.Install(_harmony);
			((MonoBehaviour)this).StartCoroutine(MinecraftSpawnGuarantee.Loop());
			if (GuaranteeMinecraftZombie.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"MCZombie Minecraft quota replacement active.");
			}
		}

		private void InstallPaintedUtilsPatchGuard()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "PaintedUtils", StringComparison.OrdinalIgnoreCase));
				if (assembly == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"PaintedUtils assembly not loaded yet.");
					return;
				}
				Type type = assembly.GetType("PaintedUtils.PaintedUtils", throwOnError: false);
				if (type == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"PaintedUtils.PaintedUtils type not found.");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "Patch", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"PaintedUtils.Patch() not found.");
					return;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(PaintedUtilsCompat), "SkipLegacyPatchAll", (Type[])null, (Type[])null);
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"PaintedUtils legacy PatchAll guarded for REPOLib 4.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to install PaintedUtils compatibility guard: " + ex));
			}
		}

		private void InstallMCZombieAwakePatch()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "MCZombieMod", StringComparison.OrdinalIgnoreCase));
				if (assembly == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"MCZombieMod assembly is not loaded yet.");
					return;
				}
				Type type = assembly.GetType("MCZombieMod.MCZombieMod", throwOnError: false);
				if (type == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"MCZombieMod.MCZombieMod type not found.");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"MCZombieMod.Awake() not found.");
					return;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(MCZombieAwakeCompat), "Prefix", (Type[])null, (Type[])null);
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"MCZombieMod.Awake compatibility patch installed BEFORE MCZombie startup.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to install MCZombie compatibility patch: " + ex));
			}
		}
	}
	internal static class ValuableCompat
	{
		internal static GameObject SpawnLegacy(object valuable, Vector3 position, Quaternion rotation)
		{
			//IL_00aa: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_0185: 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)
			try
			{
				if (valuable == null)
				{
					return null;
				}
				GameObject val = ToGameObject(valuable);
				Type? obj = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.Valuables", throwOnError: false);
				if (obj == null)
				{
					throw new MissingMemberException("REPOLib.Modules.Valuables not found.");
				}
				foreach (MethodInfo item in from m in obj.GetMethods(BindingFlags.Static | BindingFlags.Public)
					where m.Name == "SpawnValuable"
					select m)
				{
					object[] array = TryBuildArgs(item.GetParameters(), valuable, val, position, rotation);
					if (array == null)
					{
						continue;
					}
					try
					{
						GameObject val2 = ToGameObject(item.Invoke(null, array));
						if ((Object)val2 != (Object)null)
						{
							Plugin.Log.LogInfo((object)("PaintedUtils: legacy SpawnValuable adapted through " + Describe(item) + "."));
							return val2;
						}
					}
					catch (TargetInvocationException ex)
					{
						Plugin.Log.LogWarning((object)("SpawnValuable overload failed: " + (ex.InnerException?.Message ?? ex.Message)));
					}
					catch (Exception ex2)
					{
						Plugin.Log.LogWarning((object)("SpawnValuable overload failed: " + ex2.Message));
					}
				}
				if ((Object)val != (Object)null && IsHostOrSingleplayer())
				{
					GameObject result = Object.Instantiate<GameObject>(val, position, rotation);
					Plugin.Log.LogWarning((object)"PaintedUtils: no modern SpawnValuable overload matched; used host-only local Instantiate fallback.");
					return result;
				}
				Plugin.Log.LogWarning((object)"PaintedUtils: no compatible modern SpawnValuable overload found.");
				return null;
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogError((object)("PaintedUtils SpawnValuable compatibility failed: " + ex3));
				return null;
			}
		}

		internal static ValuableObject GetByNameLegacy(string valuableName)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			if (string.IsNullOrEmpty(valuableName))
			{
				return null;
			}
			try
			{
				Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.Valuables", throwOnError: false);
				if (type != null)
				{
					foreach (MethodInfo item in type.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(delegate(MethodInfo m)
					{
						ParameterInfo[] parameters = m.GetParameters();
						return parameters.Length == 1 && parameters[0].ParameterType == typeof(string) && (m.Name.IndexOf("Valuable", StringComparison.OrdinalIgnoreCase) >= 0 || m.Name.IndexOf("Prefab", StringComparison.OrdinalIgnoreCase) >= 0);
					}))
					{
						try
						{
							ValuableObject val = ToValuableObject(item.Invoke(null, new object[1] { valuableName }));
							if ((Object)val != (Object)null)
							{
								Plugin.Log.LogInfo((object)("PaintedUtils: legacy GetValuableByName adapted through " + Describe(item) + " for '" + valuableName + "'."));
								return val;
							}
						}
						catch
						{
						}
					}
				}
				ValuableObject[] array = Resources.FindObjectsOfTypeAll<ValuableObject>();
				string text = NormalizeName(valuableName);
				ValuableObject[] array2 = array;
				foreach (ValuableObject val2 in array2)
				{
					if (!((Object)val2 == (Object)null) && NormalizeName(((Object)((Component)val2).gameObject != (Object)null) ? ((Object)((Component)val2).gameObject).name : ((Object)val2).name) == text)
					{
						Plugin.Log.LogInfo((object)("PaintedUtils: legacy GetValuableByName resolved from loaded assets for '" + valuableName + "'."));
						return val2;
					}
				}
				Plugin.Log.LogWarning((object)("PaintedUtils: valuable not found by legacy name '" + valuableName + "'."));
				return null;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("PaintedUtils GetValuableByName compatibility failed: " + ex));
				return null;
			}
		}

		private static ValuableObject ToValuableObject(object value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			if (value == null)
			{
				return null;
			}
			ValuableObject val = (ValuableObject)((value is ValuableObject) ? value : null);
			if ((Object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = (GameObject)((value is GameObject) ? value : null);
			if ((Object)val2 != (Object)null)
			{
				return val2.GetComponent<ValuableObject>();
			}
			Component val3 = (Component)((value is Component) ? value : null);
			if ((Object)val3 != (Object)null)
			{
				return val3.GetComponent<ValuableObject>();
			}
			Type type = value.GetType();
			string[] array = new string[6] { "Prefab", "prefab", "Value", "value", "GameObject", "gameObject" };
			foreach (string name in array)
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.GetIndexParameters().Length == 0)
				{
					try
					{
						ValuableObject val4 = ToValuableObject(property.GetValue(value, null));
						if ((Object)val4 != (Object)null)
						{
							return val4;
						}
					}
					catch
					{
					}
				}
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field != null))
				{
					continue;
				}
				try
				{
					ValuableObject val5 = ToValuableObject(field.GetValue(value));
					if ((Object)val5 != (Object)null)
					{
						return val5;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static string NormalizeName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			string text = value.Trim();
			if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(0, text.Length - 7).Trim();
			}
			return new string(text.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray());
		}

		private static object[] TryBuildArgs(ParameterInfo[] parameters, object valuable, GameObject prefab, Vector3 position, Quaternion rotation)
		{
			//IL_002f: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				Type parameterType = parameterInfo.ParameterType;
				if (parameterType == typeof(Vector3))
				{
					array[i] = position;
					continue;
				}
				if (parameterType == typeof(Quaternion))
				{
					array[i] = rotation;
					continue;
				}
				if (parameterType.IsInstanceOfType(valuable))
				{
					array[i] = valuable;
					continue;
				}
				if (parameterType == typeof(GameObject))
				{
					array[i] = prefab;
					continue;
				}
				if (parameterType == typeof(string))
				{
					array[i] = (((Object)prefab != (Object)null) ? ((Object)prefab).name : string.Empty);
					continue;
				}
				object obj = null;
				if (parameterType.Name.IndexOf("PrefabRef", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					obj = FindValuablePrefabRef(parameterType, prefab);
					if (obj == null)
					{
						obj = ConstructPrefabRef(parameterType, prefab);
					}
				}
				if (obj != null && parameterType.IsInstanceOfType(obj))
				{
					array[i] = obj;
					continue;
				}
				if (parameterInfo.HasDefaultValue)
				{
					array[i] = parameterInfo.DefaultValue;
					continue;
				}
				if (parameterType == typeof(bool))
				{
					array[i] = false;
					continue;
				}
				if (parameterType.IsValueType)
				{
					array[i] = Activator.CreateInstance(parameterType);
					continue;
				}
				return null;
			}
			return array;
		}

		private static object FindValuablePrefabRef(Type expectedType, GameObject prefab)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			if ((Object)prefab == (Object)null)
			{
				return null;
			}
			try
			{
				if (!(((AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase))?.GetType("REPOLib.Modules.Valuables", throwOnError: false))?.GetProperty("AllValuables", BindingFlags.Static | BindingFlags.Public))?.GetValue(null, null) is IEnumerable enumerable))
				{
					return null;
				}
				object obj = null;
				foreach (object item in enumerable)
				{
					if (item == null || !expectedType.IsInstanceOfType(item))
					{
						continue;
					}
					GameObject val = ToGameObject(item);
					if (!((Object)val == (Object)null))
					{
						if ((Object)(object)val == (Object)(object)prefab)
						{
							return item;
						}
						if (obj == null && string.Equals(((Object)val).name, ((Object)prefab).name, StringComparison.OrdinalIgnoreCase))
						{
							obj = item;
						}
					}
				}
				return obj;
			}
			catch
			{
				return null;
			}
		}

		private static object ConstructPrefabRef(Type targetType, GameObject prefab)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			if (targetType == null || (Object)prefab == (Object)null)
			{
				return null;
			}
			try
			{
				ConstructorInfo[] constructors = targetType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (ConstructorInfo constructorInfo in constructors)
				{
					ParameterInfo[] parameters = constructorInfo.GetParameters();
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject))
					{
						return constructorInfo.Invoke(new object[1] { prefab });
					}
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
					{
						return constructorInfo.Invoke(new object[1] { ((Object)prefab).name });
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static GameObject ToGameObject(object value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			if (value == null)
			{
				return null;
			}
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Component val2 = (Component)((value is Component) ? value : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.gameObject;
			}
			Type type = value.GetType();
			string[] array = new string[4] { "gameObject", "GameObject", "prefab", "Prefab" };
			foreach (string name in array)
			{
				try
				{
					PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.GetIndexParameters().Length == 0)
					{
						object value2 = property.GetValue(value, null);
						if (value2 != value)
						{
							GameObject val3 = ToGameObject(value2);
							if ((Object)val3 != (Object)null)
							{
								return val3;
							}
						}
					}
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field != null))
					{
						continue;
					}
					object value3 = field.GetValue(value);
					if (value3 != value)
					{
						GameObject val4 = ToGameObject(value3);
						if ((Object)val4 != (Object)null)
						{
							return val4;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static bool IsHostOrSingleplayer()
		{
			try
			{
				Type type = Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking");
				if (type == null)
				{
					return true;
				}
				PropertyInfo property = type.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public);
				if (!(property != null) || !Convert.ToBoolean(property.GetValue(null, null)))
				{
					return true;
				}
				PropertyInfo property2 = type.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public);
				return property2 != null && Convert.ToBoolean(property2.GetValue(null, null));
			}
			catch
			{
				return false;
			}
		}

		private static string Describe(MethodInfo method)
		{
			return method.DeclaringType?.FullName + "." + method.Name + "(" + string.Join(", ", (from p in method.GetParameters()
				select p.ParameterType.Name).ToArray()) + ")";
		}
	}
	internal static class ZombieGrabFix
	{
		private static FieldInfo _enemyField;

		private static FieldInfo _photonViewField;

		private static FieldInfo _targetPlayerField;

		private static FieldInfo _currentStateField;

		private static MethodInfo _updateState;

		private static Type _stateType;

		private static readonly FieldInfo EnemyVisionField = AccessTools.Field(typeof(Enemy), "Vision");

		private static readonly FieldInfo EnemyRigidbodyField = AccessTools.Field(typeof(Enemy), "Rigidbody");

		private static readonly FieldInfo VisionPlayerField = AccessTools.Field(typeof(EnemyVision), "onVisionTriggeredPlayer");

		private static readonly FieldInfo RigidbodyGrabObjectField = AccessTools.Field(typeof(EnemyRigidbody), "physGrabObject");

		private static readonly FieldInfo GrabbersField = AccessTools.Field(typeof(PhysGrabObject), "playerGrabbing");

		private static readonly FieldInfo GrabberAvatarField = AccessTools.Field(typeof(PhysGrabber), "playerAvatar");

		internal static void Install(Harmony harmony)
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("MCZombieMod.AI.EnemyMCZombie");
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "OnGrabbed", (Type[])null, (Type[])null) : null);
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"MCZombie grab fix unavailable: EnemyMCZombie.OnGrabbed not found.");
				return;
			}
			_enemyField = AccessTools.Field(type, "_enemy");
			_photonViewField = AccessTools.Field(type, "_photonView");
			_targetPlayerField = AccessTools.Field(type, "_targetPlayer");
			_currentStateField = AccessTools.Field(type, "currentState");
			_stateType = AccessTools.Inner(type, "State");
			_updateState = ((_stateType != null) ? AccessTools.Method(type, "UpdateState", new Type[1] { _stateType }, (Type[])null) : null);
			if (_enemyField == null || _photonViewField == null || _targetPlayerField == null || _currentStateField == null || _updateState == null)
			{
				Plugin.Log.LogWarning((object)"MCZombie grab fix unavailable: EnemyMCZombie members changed.");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ZombieGrabFix), "OnGrabbedPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Plugin.Log.LogInfo((object)"MCZombie grab fix installed.");
		}

		private static bool OnGrabbedPrefix(MonoBehaviour __instance)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			try
			{
				if (!SemiFunc.IsMasterClientOrSingleplayer())
				{
					return false;
				}
				switch (Convert.ToString(_currentStateField.GetValue(__instance)))
				{
				case "Attack":
				case "Chase":
				case "Stun":
					return false;
				default:
				{
					object? value = _enemyField.GetValue(__instance);
					PlayerAvatar val = FindTarget((Enemy)((value is Enemy) ? value : null));
					if ((Object)val == (Object)null)
					{
						return false;
					}
					_targetPlayerField.SetValue(__instance, val);
					if (SemiFunc.IsMultiplayer())
					{
						object? value2 = _photonViewField.GetValue(__instance);
						PhotonView val2 = (PhotonView)((value2 is PhotonView) ? value2 : null);
						if (val2 != null && (Object)val.photonView != (Object)null)
						{
							val2.RPC("UpdatePlayerTargetRPC", (RpcTarget)0, new object[1] { val.photonView.ViewID });
						}
					}
					_updateState.Invoke(__instance, new object[1] { Enum.Parse(_stateType, "Chase") });
					break;
				}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("MCZombie grab fix: " + ex.Message));
			}
			return false;
		}

		private static PlayerAvatar FindTarget(Enemy enemy)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			if ((Object)enemy == (Object)null)
			{
				return null;
			}
			object obj = EnemyVisionField?.GetValue(enemy);
			if (obj != null)
			{
				object? obj2 = VisionPlayerField?.GetValue(obj);
				PlayerAvatar val = (PlayerAvatar)((obj2 is PlayerAvatar) ? obj2 : null);
				if (val != null && (Object)val != (Object)null)
				{
					return val;
				}
			}
			object obj3 = EnemyRigidbodyField?.GetValue(enemy);
			object obj4 = ((obj3 == null) ? null : RigidbodyGrabObjectField?.GetValue(obj3));
			if (obj4 != null && GrabbersField?.GetValue(obj4) is IList list)
			{
				foreach (object item in list)
				{
					if (item != null)
					{
						object? obj5 = GrabberAvatarField?.GetValue(item);
						PlayerAvatar val2 = (PlayerAvatar)((obj5 is PlayerAvatar) ? obj5 : null);
						if (val2 != null && (Object)val2 != (Object)null)
						{
							return val2;
						}
					}
				}
			}
			return null;
		}
	}
}