Decompiled source of ExtendedCore v1.0.3

BepInEx/patchers/SlipAndSkid.ExtendedCore.AudioBootstrap.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx.Preloader.Core.Patching;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.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 SlipSkid.RaceWorkshop.AudioBootstrap
{
	[PatcherPluginInfo("slipandskid.extendedcore.audio", "Slip & Skid Extended Core Audio Bootstrap", "0.1.0")]
	public sealed class WorkshopAudioPatcher : BasePatcher
	{
		[TargetType("UnityEngine.AudioModule.dll", "UnityEngine.AudioClip")]
		public bool Restore(TypeDefinition clip)
		{
			return RestoreBindings(clip);
		}

		[TargetType("UnityEngine.AudioModule.dll", "UnityEngine.AudioSource")]
		public bool RestoreSource(TypeDefinition source)
		{
			return RestoreSourceBindings(source);
		}

		public static bool RestoreSourceBindings(TypeDefinition source)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			if (((IEnumerable<MethodDefinition>)source.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == "UnPause" && !m.IsStatic && ((MethodReference)m).Parameters.Count == 0))
			{
				return false;
			}
			source.Methods.Add(new MethodDefinition("UnPause", (MethodAttributes)134, ((MemberReference)source).Module.TypeSystem.Void)
			{
				ImplAttributes = ((IEnumerable<MethodDefinition>)source.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == "Pause").ImplAttributes
			});
			return true;
		}

		public static bool RestoreBindings(TypeDefinition clip)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			TypeSystem typeSystem = ((MemberReference)clip).Module.TypeSystem;
			return (byte)(0u | (Add(clip, "Construct_Internal", true, (TypeReference)(object)clip) ? 1u : 0u) | (Add(clip, "CreateUserSound", false, typeSystem.Void, typeSystem.String, typeSystem.Int32, typeSystem.Int32, typeSystem.Int32, typeSystem.Boolean) ? 1u : 0u) | (Add(clip, "SetData", true, typeSystem.Boolean, (TypeReference)clip, (TypeReference)new ArrayType(typeSystem.Single), typeSystem.Int32, typeSystem.Int32) ? 1u : 0u)) != 0;
		}

		private static bool Add(TypeDefinition type, string name, bool isStatic, TypeReference result, params TypeReference[] parameters)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			if (((IEnumerable<MethodDefinition>)type.Methods).Any((MethodDefinition m) => ((MemberReference)m).Name == name && m.IsStatic == isStatic && ((IEnumerable<ParameterDefinition>)((MethodReference)m).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName).SequenceEqual(parameters.Select((TypeReference p) => ((MemberReference)p).FullName))))
			{
				return false;
			}
			MethodDefinition val = new MethodDefinition(name, (MethodAttributes)(1 | (isStatic ? 16 : 0) | 0x80), result)
			{
				ImplAttributes = ((IEnumerable<MethodDefinition>)type.Methods).First((MethodDefinition m) => ((MemberReference)m).Name == "GetName").ImplAttributes
			};
			for (int num = 0; num < parameters.Length; num++)
			{
				((MethodReference)val).Parameters.Add(new ParameterDefinition("arg" + num, (ParameterAttributes)0, parameters[num]));
			}
			type.Methods.Add(val);
			return true;
		}
	}
}

BepInEx/plugins/SlipAndSkid.ExtendedCore/SlipAndSkid.ExtendedCore.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.Mono;
using Game;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Obstacles;
using Obstacles.ObstacleAffixes;
using Obstacles.ObstacleGenerationContexts;
using Player;
using UI;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Localization;
using Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Slip & Skid Extended Core")]
[assembly: AssemblyDescription("Public card registration, native placement integration and versioned multiplayer messaging for Slip & Skid mods.")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.0.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 SlipAndSkid.ExtendedCore
{
	public enum CardTemplate
	{
		Prop,
		DeleteTool,
		Modifier
	}
	public sealed class CardDefinition
	{
		public string Id { get; set; }

		public string ModuleId { get; set; }

		public string Name { get; set; }

		public string Description { get; set; }

		public CardTemplate Template { get; set; }

		public ObstacleRarity Rarity { get; set; } = (ObstacleRarity)2;

		public Func<ObstacleRarity> ResolveRarity { get; set; }

		public bool Hidden { get; set; }

		public int? LegacyAffixTag { get; set; }

		public Func<Texture2D> LoadArtwork { get; set; }

		public Action<CorePlacedObject> Attach { get; set; }

		public Action<Obstacle> NetworkSpawned { get; set; }

		public Action<PlayerData> ModifierSelected { get; set; }
	}
	public sealed class CardHandle
	{
		internal readonly CardDefinition Definition;

		internal ObstacleDescription Source;

		public string Id => Definition.Id;

		public int AffixTag { get; internal set; }

		public ObstacleDescription Description { get; internal set; }

		internal CardHandle(CardDefinition d)
		{
			Definition = d;
		}
	}
	public static class ContactRules
	{
		public static bool Finite(double value)
		{
			if (!double.IsNaN(value))
			{
				return !double.IsInfinity(value);
			}
			return false;
		}

		public static double Allowance(double speed)
		{
			if (!Finite(speed) || !(speed >= 0.0))
			{
				return -1.0;
			}
			return Math.Min(20.0, 2.0 + speed * 0.5);
		}

		public static bool Plausible(double distanceSquared, double speed)
		{
			double num = Allowance(speed);
			if (Finite(distanceSquared) && distanceSquared >= 0.0 && num >= 0.0)
			{
				return distanceSquared <= num * num;
			}
			return false;
		}
	}
	public static class CoreArtwork
	{
		public static Texture2D Load(string path, Func<Texture2D> fallback, Action<string> warn)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			Texture2D val = null;
			try
			{
				if (!File.Exists(path))
				{
					return fallback();
				}
				FileInfo fileInfo = new FileInfo(path);
				if (fileInfo.Length < 33 || fileInfo.Length > 8388608)
				{
					throw new InvalidDataException("PNG must be between 33 bytes and 8 MiB.");
				}
				byte[] array = File.ReadAllBytes(path);
				byte[] array2 = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };
				for (int i = 0; i < array2.Length; i++)
				{
					if (array[i] != array2[i])
					{
						throw new InvalidDataException("Not a PNG file.");
					}
				}
				if (ReadUInt(array, 8) != 13 || array[12] != 73 || array[13] != 72 || array[14] != 68 || array[15] != 82)
				{
					throw new InvalidDataException("Missing PNG image header.");
				}
				uint num = ReadUInt(array, 16);
				uint num2 = ReadUInt(array, 20);
				if (num == 0 || num2 == 0 || num > 2048 || num2 > 2048)
				{
					throw new InvalidDataException("PNG dimensions must be 1–2048 pixels.");
				}
				val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, array, true))
				{
					throw new InvalidDataException("Unity could not decode PNG.");
				}
				((Object)val).name = Path.GetFileNameWithoutExtension(path) + " artwork";
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				return val;
			}
			catch (Exception ex)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
				warn("Card artwork skipped: " + path + " (" + ex.Message + "). Using default icon.");
				return fallback();
			}
		}

		public static Texture2D DefaultIcon(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					val.SetPixel(j, i, (Color)((j > 9 && j < 54 && i > 9 && i < 54) ? color : new Color(0.04f, 0.05f, 0.08f, 1f)));
				}
			}
			val.Apply();
			return val;
		}

		private static uint ReadUInt(byte[] bytes, int offset)
		{
			return (uint)((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]);
		}
	}
	[HarmonyPatch(typeof(ObstacleManager), "Awake")]
	internal static class CoreCatalogPatch
	{
		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "slipskid.tankcards", "slipskid.chaossystems", "slipskid.chaoscards" })]
		private static void Postfix()
		{
			CoreCards.EnsureCatalog();
		}
	}
	[HarmonyPatch(typeof(ObstacleManager), "GetRandomObstaclesDescriptions")]
	internal static class CoreDraftCatalogPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix()
		{
			CoreCards.EnsureCatalog();
		}
	}
	[HarmonyPatch(typeof(GameManager), "GenerateObstaclesToSelect")]
	internal static class CoreModifierDraftPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			CoreCards.BeginDraft();
		}
	}
	[HarmonyPatch(typeof(GameManager), "GenerateObstaclesToSelect")]
	internal static class CoreForceDraftPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(GameManager __instance)
		{
			CorePlugin instance = CorePlugin.Instance;
			if (!Object.op_Implicit((Object)(object)instance) || !instance.Host || string.IsNullOrWhiteSpace(instance.ForcedDraftId))
			{
				return;
			}
			CoreCards.EnsureCatalog();
			CardHandle cardHandle = CoreCards.Find(instance.ForcedDraftId.Trim());
			if (cardHandle == null || !Object.op_Implicit((Object)(object)cardHandle.Description) || cardHandle.Definition.Hidden)
			{
				instance.Note("Forced draft card is not an available registered card: " + instance.ForcedDraftId);
				return;
			}
			(int, ObstacleDescription)[] array = AccessTools.Field(typeof(GameManager), "_obstaclesToSelect").GetValue(__instance) as (int, ObstacleDescription)[];
			(int, ObstacleAffixDescription)[] array2 = AccessTools.Field(typeof(GameManager), "_obstacleAffixDescriptions").GetValue(__instance) as (int, ObstacleAffixDescription)[];
			if (array == null || array.Length == 0)
			{
				return;
			}
			int num = array.Length - 1;
			int indexFromDescription = ObstacleManager.GetIndexFromDescription(cardHandle.Description, false);
			if (indexFromDescription >= 0)
			{
				array[num] = (indexFromDescription, cardHandle.Description);
				__instance.networkVariables.obstaclesToSelectIndices[num] = indexFromDescription;
				if (array2 != null && num < array2.Length)
				{
					array2[num] = (0, ObstacleAffixManager.None);
					__instance.networkVariables.obstaclesModifiersIndices[num] = 0;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ObstacleDescription), "Spawn", new Type[]
	{
		typeof(PlayerData),
		typeof(Vector3),
		typeof(Quaternion),
		typeof(Vector3),
		typeof(bool),
		typeof(int)
	})]
	internal static class CoreSpawnPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ObstacleDescription __instance, PlayerData __0, Vector3 __1, Quaternion __2, Vector3 __3, bool __4, int __5, ref Obstacle __result)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			CardHandle cardHandle = CoreCards.Find(SerializableGuid.op_Implicit(__instance.id));
			if (cardHandle == null)
			{
				return true;
			}
			CoreCards.EnsureCatalog();
			if (cardHandle.Definition.Template == CardTemplate.Modifier)
			{
				CoreCards.NotifyModifier(cardHandle, __0);
				__result = null;
				return false;
			}
			__result = (Object.op_Implicit((Object)(object)cardHandle.Source) ? cardHandle.Source.Spawn(__0, __1, __2, __3, __4, cardHandle.AffixTag) : null);
			return false;
		}
	}
	[HarmonyPatch(typeof(Obstacle), "OnNetworkSpawn")]
	internal static class CoreObjectPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Obstacle __instance)
		{
			CardHandle cardHandle = CoreCards.Find(__instance.affixIndex.Value);
			if (cardHandle != null)
			{
				CoreCards.EnsureCatalog();
				if (Object.op_Implicit((Object)(object)cardHandle.Description))
				{
					__instance.description = cardHandle.Description;
				}
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Obstacle __instance)
		{
			CardHandle cardHandle = CoreCards.Find(__instance.affixIndex.Value);
			if (cardHandle != null)
			{
				if (cardHandle.Definition.Template == CardTemplate.Prop && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CorePlacedObject>()))
				{
					((Component)__instance).gameObject.AddComponent<CorePlacedObject>().Initialize(__instance, cardHandle);
				}
				cardHandle.Definition.NetworkSpawned?.Invoke(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(LocalizedString), "GetLocalizedString", new Type[] { })]
	internal static class CoreLocalePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(LocalizedString __instance, ref string __result)
		{
			if (CoreCards.LocalText(__instance, out var value))
			{
				__result = value;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(TextProcessor), "Process", new Type[] { typeof(LocalizedString) })]
	internal static class CoreTextPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(LocalizedString __0, ref string __result)
		{
			if (CoreCards.LocalText(__0, out var value))
			{
				__result = value;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GameManager), "CheckIfPlayersPlacedObstacles")]
	internal static class CoreModifierCompletionPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			CoreCards.CompleteModifierPlacements();
		}
	}
	[HarmonyPatch(typeof(GameManager), "StartGame")]
	internal static class CoreStartPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (Object.op_Implicit((Object)(object)CorePlugin.Instance))
			{
				return CorePlugin.Instance.CanStart();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GameManager), "CleanUpGame")]
	internal static class CoreCleanupPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (Object.op_Implicit((Object)(object)CorePlugin.Instance))
			{
				CorePlugin.Instance.MatchEnded();
			}
		}
	}
	public static class CoreCards
	{
		private sealed class ReferenceComparer : IEqualityComparer<LocalizedString>
		{
			public bool Equals(LocalizedString a, LocalizedString b)
			{
				return a == b;
			}

			public int GetHashCode(LocalizedString s)
			{
				return RuntimeHelpers.GetHashCode(s);
			}
		}

		private static readonly RegistrationTable<CardHandle> table = new RegistrationTable<CardHandle>();

		private static CardHandle[] ordered;

		private static ObstacleManager catalogOwner;

		private static ObstacleDescription[] lastAllowed;

		private static ObstacleDescription[] lastHidden;

		private static int installedCount = -1;

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

		private static readonly Dictionary<LocalizedString, string> text = new Dictionary<LocalizedString, string>(new ReferenceComparer());

		internal static IEnumerable<CardHandle> Entries => ordered ?? (ordered = table.Ids.Select(delegate(string id)
		{
			table.TryGet(id, out var value);
			return value;
		}).ToArray());

		public static int Count => table.Count;

		public static CardHandle Register(CardDefinition definition)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (definition == null)
			{
				throw new ArgumentNullException("definition");
			}
			if (Object.op_Implicit((Object)(object)NetworkManager.Singleton) && NetworkManager.Singleton.IsListening)
			{
				throw new InvalidOperationException("Register cards before joining a network lobby.");
			}
			if (!Object.op_Implicit((Object)(object)CorePlugin.Instance))
			{
				throw new InvalidOperationException("Extended Core must load before its dependent mods.");
			}
			CorePlugin.Instance.RequireModule(definition.ModuleId);
			if (string.IsNullOrWhiteSpace(definition.Name))
			{
				throw new ArgumentException("Card name is required.");
			}
			CardDefinition cardDefinition = new CardDefinition
			{
				Id = definition.Id,
				ModuleId = definition.ModuleId,
				Name = definition.Name,
				Description = (definition.Description ?? ""),
				Template = definition.Template,
				Rarity = definition.Rarity,
				ResolveRarity = definition.ResolveRarity,
				Hidden = definition.Hidden,
				LegacyAffixTag = definition.LegacyAffixTag,
				LoadArtwork = definition.LoadArtwork,
				Attach = definition.Attach,
				NetworkSpawned = definition.NetworkSpawned,
				ModifierSelected = definition.ModifierSelected
			};
			CardHandle cardHandle = new CardHandle(cardDefinition);
			cardHandle.AffixTag = table.Add(cardDefinition.Id, cardHandle, cardDefinition.LegacyAffixTag);
			ordered = null;
			installedCount = -1;
			return cardHandle;
		}

		public static CardHandle Find(string id)
		{
			if (id == null || !table.TryGet(id, out var value))
			{
				return null;
			}
			return value;
		}

		internal static CardHandle Find(int tag)
		{
			if (!table.TryGet(tag, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void Freeze()
		{
			table.Freeze();
		}

		internal static void Unfreeze()
		{
			table.Unfreeze();
		}

		internal static bool LocalText(LocalizedString key, out string value)
		{
			if (key != null)
			{
				return text.TryGetValue(key, out value);
			}
			value = null;
			return false;
		}

		private static LocalizedString Copy(LocalizedString value)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (value == null)
			{
				return new LocalizedString();
			}
			return new LocalizedString
			{
				TableReference = ((LocalizedReference)value).TableReference,
				TableEntryReference = ((LocalizedReference)value).TableEntryReference
			};
		}

		public static void EnsureCatalog()
		{
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			ObstacleManager instance = ObstacleManager.instance;
			if (!Object.op_Implicit((Object)(object)instance) || instance.allowedObstacleDescriptions == null || instance.allowedObstacleDescriptions.Length == 0 || ((Object)(object)catalogOwner == (Object)(object)instance && lastAllowed == instance.allowedObstacleDescriptions && lastHidden == instance.hiddenObstacleDescriptions && installedCount == table.Count))
			{
				return;
			}
			ObstacleDescription[] source = (from d in instance.allowedObstacleDescriptions.Concat((IEnumerable<ObstacleDescription>)(((object)instance.hiddenObstacleDescriptions) ?? ((object)new ObstacleDescription[0])))
				where Object.op_Implicit((Object)(object)d)
				select d).ToArray();
			foreach (CardHandle entry in Entries)
			{
				CardDefinition definition = entry.Definition;
				if (Object.op_Implicit((Object)(object)entry.Description))
				{
					continue;
				}
				if (Object.op_Implicit((Object)(object)((IEnumerable<ObstacleDescription>)source).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => d.id == definition.Id))))
				{
					throw new InvalidOperationException("Card ID already registered outside Extended Core: " + definition.Id);
				}
				ObstacleDescription val = null;
				val = ((definition.Template == CardTemplate.Prop) ? ((IEnumerable<ObstacleDescription>)source).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => d.id == "bed8133d-50d9-43f9-a313-d5331e2727a6")) : ((definition.Template != CardTemplate.DeleteTool) ? ((IEnumerable<ObstacleDescription>)source).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => Find(SerializableGuid.op_Implicit(d.id)) == null && (int)d.type == 4 && Object.op_Implicit((Object)(object)d.prefab))) : ((IEnumerable<ObstacleDescription>)source).FirstOrDefault((Func<ObstacleDescription, bool>)((ObstacleDescription d) => Find(SerializableGuid.op_Implicit(d.id)) == null && Object.op_Implicit((Object)(object)d.prefab) && Object.op_Implicit((Object)(object)((Component)d.prefab).GetComponent<ObstacleDelete>())))));
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				entry.Source = val;
				ObstacleDescription val2 = Object.Instantiate<ObstacleDescription>(val);
				((Object)val2).name = definition.Name;
				val2.id = SerializableGuid.op_Implicit(definition.Id);
				val2.maxQuantity = -1;
				val2.rarity = ((definition.ResolveRarity != null) ? definition.ResolveRarity() : definition.Rarity);
				val2.generationContexts = (ObstacleDescriptionGenerationContext[])(object)new ObstacleDescriptionGenerationContext[0];
				val2.allowedAffixes = (ObstacleAffixDescription[])(object)new ObstacleAffixDescription[0];
				val2.displayName = Copy(val.displayName);
				val2.description = Copy(val.description);
				text[val2.displayName] = definition.Name;
				text[val2.description] = definition.Description;
				try
				{
					if (definition.LoadArtwork != null)
					{
						val2.thumbnail = definition.LoadArtwork();
					}
				}
				catch (Exception ex)
				{
					CorePlugin.Instance.Note("Artwork fallback for " + definition.Id + ": " + ex.Message);
				}
				entry.Description = val2;
			}
			ObstacleDescription[] second = (from h in Entries
				where Object.op_Implicit((Object)(object)h.Description) && !h.Definition.Hidden
				select h.Description).ToArray();
			ObstacleDescription[] second2 = (from h in Entries
				where Object.op_Implicit((Object)(object)h.Description) && h.Definition.Hidden
				select h.Description).ToArray();
			instance.allowedObstacleDescriptions = instance.allowedObstacleDescriptions.Where((ObstacleDescription d) => !Object.op_Implicit((Object)(object)d) || Find(SerializableGuid.op_Implicit(d.id)) == null).Concat(second).ToArray();
			instance.hiddenObstacleDescriptions = ((IEnumerable<ObstacleDescription>)(((object)instance.hiddenObstacleDescriptions) ?? ((object)new ObstacleDescription[0]))).Where((ObstacleDescription d) => !Object.op_Implicit((Object)(object)d) || Find(SerializableGuid.op_Implicit(d.id)) == null).Concat(second2).ToArray();
			catalogOwner = instance;
			lastAllowed = instance.allowedObstacleDescriptions;
			lastHidden = instance.hiddenObstacleDescriptions;
			installedCount = Entries.Count((CardHandle h) => Object.op_Implicit((Object)(object)h.Description));
		}

		internal static void BeginDraft()
		{
			modifierSelections.Clear();
		}

		internal static void NotifyModifier(CardHandle card, PlayerData player)
		{
			if (CorePlugin.Instance.Host && Object.op_Implicit((Object)(object)player))
			{
				string item = card.Id + ":" + ((NetworkBehaviour)player).NetworkObjectId;
				if (modifierSelections.Add(item))
				{
					card.Definition.ModifierSelected?.Invoke(player);
				}
			}
		}

		internal static void CompleteModifierPlacements()
		{
			GameManager instance = GameManager.instance;
			ObstacleManager instance2 = ObstacleManager.instance;
			if (!Object.op_Implicit((Object)(object)instance2) || !CoreGame.IsState((GameState)8))
			{
				return;
			}
			NetworkList<int> obstaclesToSelectIndices = instance.networkVariables.obstaclesToSelectIndices;
			ObstacleDescription[] allowedObstacleDescriptions = instance2.allowedObstacleDescriptions;
			if (obstaclesToSelectIndices == null || allowedObstacleDescriptions == null)
			{
				return;
			}
			foreach (PlayerData player in CoreGame.Players)
			{
				if (!Object.op_Implicit((Object)(object)player) || !player.selectedObstacle.Value)
				{
					continue;
				}
				int value = player.selectedObstacleIndex.Value;
				if (value < 0 || value >= obstaclesToSelectIndices.Count)
				{
					continue;
				}
				int num = obstaclesToSelectIndices[value];
				if (num < 0 || num >= allowedObstacleDescriptions.Length || !Object.op_Implicit((Object)(object)allowedObstacleDescriptions[num]))
				{
					continue;
				}
				CardHandle cardHandle = Find(SerializableGuid.op_Implicit(allowedObstacleDescriptions[num].id));
				if (cardHandle != null && cardHandle.Definition.Template == CardTemplate.Modifier)
				{
					NotifyModifier(cardHandle, player);
					if (((NetworkBehaviour)player).IsOwner && !player.placedObstacle.Value)
					{
						player.placedObstacle.Value = true;
					}
				}
			}
		}
	}
	public static class CoreContact
	{
		private static bool Finite(Vector3 value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (ContactRules.Finite(value.x) && ContactRules.Finite(value.y))
			{
				return ContactRules.Finite(value.z);
			}
			return false;
		}

		public static bool Validate(PlayerData player, Vector3 reportedPosition, Vector3 reportedVelocity)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)player.controller) || !Object.op_Implicit((Object)(object)player.controller.sphereRigidbody) || !Finite(reportedPosition) || !Finite(reportedVelocity))
			{
				return false;
			}
			Rigidbody sphereRigidbody = player.controller.sphereRigidbody;
			if (!Finite(sphereRigidbody.position) || !Finite(sphereRigidbody.velocity))
			{
				return false;
			}
			Vector3 val = sphereRigidbody.velocity;
			float num = Mathf.Max(((Vector3)(ref val)).magnitude, Mathf.Min(160f, ((Vector3)(ref reportedVelocity)).magnitude));
			val = sphereRigidbody.position - reportedPosition;
			return ContactRules.Plausible(((Vector3)(ref val)).sqrMagnitude, num);
		}
	}
	public static class CoreGame
	{
		public static IEnumerable<PlayerData> Players
		{
			get
			{
				PlayerManager instance = PlayerManager.instance;
				if (!Object.op_Implicit((Object)(object)instance) || instance.players == null)
				{
					return Array.Empty<PlayerData>();
				}
				return instance.players;
			}
		}

		public static bool TryGetState(out GameState state)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected I4, but got Unknown
			state = (GameState)0;
			GameManager instance = GameManager.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.networkVariables) || instance.networkVariables.state == null)
			{
				return false;
			}
			state = (GameState)(int)instance.networkVariables.state.Value;
			return true;
		}

		public static bool IsState(GameState state)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetState(out var state2))
			{
				return state2 == state;
			}
			return false;
		}
	}
	public static class CoreWire
	{
		public const int MaxCharacters = 18000;

		public const int MaxReceiveBytes = 65536;

		public unsafe static void Send(NetworkManager network, string channel, ulong target, string json)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)network) || !network.IsListening || json == null || json.Length > 18000)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(FastBufferWriter.GetWriteSize(json, false), (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(json, false);
				network.CustomMessagingManager.SendNamedMessage(channel, target, val, (NetworkDelivery)4);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}
	}
	[Serializable]
	public sealed class CoreMessage
	{
		public string kind;

		public string text;

		public int player = -1;

		public int other = -1;

		public ulong objectId;

		public ulong target;

		public bool active;

		public bool hasContact;

		public float number;

		public Vector3 position;

		public Vector3 velocity;
	}
	[Serializable]
	internal sealed class CoreEnvelope
	{
		public string operation;

		public string module;

		public string session;

		public string manifest;

		public int epoch;

		public int sequence;

		public bool active;

		public CoreMessage message;
	}
	public sealed class CoreChannel
	{
		internal string Module;

		internal Action<CoreMessage> HostRequest;

		internal Action<CoreMessage> ServerEvent;

		internal bool RequiresRace;

		internal CoreChannel(string module, Action<CoreMessage> request, Action<CoreMessage> receive, bool requiresRace)
		{
			Module = module;
			HostRequest = request;
			ServerEvent = receive;
			RequiresRace = requiresRace;
		}

		public void Request(CoreMessage message)
		{
			if (Object.op_Implicit((Object)(object)CorePlugin.Instance))
			{
				CorePlugin.Instance.Request(this, message);
			}
		}

		public void Broadcast(CoreMessage message)
		{
			if (Object.op_Implicit((Object)(object)CorePlugin.Instance))
			{
				CorePlugin.Instance.Broadcast(this, message);
			}
		}
	}
	public sealed class CorePlacedObject : MonoBehaviour
	{
		private static readonly Dictionary<ulong, CorePlacedObject> objects = new Dictionary<ulong, CorePlacedObject>();

		private ulong objectId;

		private Renderer[] nativeRenderers;

		private Collider[] nativeColliders;

		private Rigidbody[] nativeBodies;

		public Obstacle Obstacle { get; private set; }

		public CardHandle Card { get; private set; }

		public GameObject Visual { get; private set; }

		public Transform Area
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Visual))
				{
					return ((Component)this).transform;
				}
				return Visual.transform;
			}
		}

		public bool Placed
		{
			get
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Invalid comparison between Unknown and I4
				if (Object.op_Implicit((Object)(object)Obstacle) && !Obstacle.Destroyed)
				{
					return (int)Obstacle.state == 3;
				}
				return false;
			}
		}

		internal void Initialize(Obstacle obstacle, CardHandle card)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Obstacle = obstacle;
			Card = card;
			nativeRenderers = ((Component)obstacle).GetComponentsInChildren<Renderer>(true);
			nativeColliders = ((Component)obstacle).GetComponentsInChildren<Collider>(true);
			nativeBodies = ((Component)obstacle).GetComponentsInChildren<Rigidbody>(true);
			Visual = new GameObject(card.Definition.Name);
			Visual.transform.SetParent(((Component)this).transform, false);
			NormalizeScale();
			objectId = ((NetworkBehaviour)obstacle).NetworkObjectId;
			objects[objectId] = this;
			try
			{
				card.Definition.Attach?.Invoke(this);
			}
			catch (Exception ex)
			{
				CorePlugin.Instance.Note("Card attach failed for " + card.Id + ": " + ex);
			}
			HideNative();
		}

		public static CorePlacedObject Find(ulong objectId, string cardId = null)
		{
			if (!objects.TryGetValue(objectId, out var value) || !Object.op_Implicit((Object)(object)value) || (cardId != null && !(value.Card.Id == cardId)))
			{
				return null;
			}
			return value;
		}

		private void NormalizeScale()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Visual))
			{
				Vector3 lossyScale = ((Component)this).transform.lossyScale;
				if (Mathf.Abs(lossyScale.x) > 0.001f && Mathf.Abs(lossyScale.y) > 0.001f && Mathf.Abs(lossyScale.z) > 0.001f)
				{
					Visual.transform.localScale = new Vector3(1f / Mathf.Abs(lossyScale.x), 1f / Mathf.Abs(lossyScale.y), 1f / Mathf.Abs(lossyScale.z));
				}
			}
		}

		private void HideNative()
		{
			Renderer[] array = nativeRenderers;
			foreach (Renderer val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					val.enabled = false;
				}
			}
			if (!Placed)
			{
				return;
			}
			Collider[] array2 = nativeColliders;
			foreach (Collider val2 in array2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.enabled = false;
				}
			}
			Rigidbody[] array3 = nativeBodies;
			foreach (Rigidbody val3 in array3)
			{
				if (Object.op_Implicit((Object)(object)val3))
				{
					val3.isKinematic = true;
				}
			}
		}

		private void Update()
		{
			NormalizeScale();
			HideNative();
		}

		private void OnDestroy()
		{
			if (objects.TryGetValue(objectId, out var value) && value == this)
			{
				objects.Remove(objectId);
			}
			if (Object.op_Implicit((Object)(object)Visual))
			{
				Object.Destroy((Object)(object)Visual);
			}
		}
	}
	[BepInPlugin("slipandskid.extendedcore", "Slip & Skid Extended Core", "1.0.3")]
	[DefaultExecutionOrder(29000)]
	public sealed class CorePlugin : BaseUnityPlugin
	{
		public const string Guid = "slipandskid.extendedcore";

		public const string Version = "1.0.3";

		public const string Channel = "slipandskid.extendedcore.protocol.v1";

		private ConfigEntry<string> forceDraft;

		private readonly Dictionary<string, string> modules = new Dictionary<string, string>(StringComparer.Ordinal);

		private readonly Dictionary<string, CoreChannel> channels = new Dictionary<string, CoreChannel>(StringComparer.Ordinal);

		private readonly HashSet<ulong> peers = new HashSet<ulong>();

		private readonly Dictionary<ulong, int> requests = new Dictionary<ulong, int>();

		private NetworkManager network;

		private Harmony harmony;

		private string session;

		private string manifest;

		private bool acknowledged;

		private bool wasCountdown;

		private float helloAt;

		private float stateAt;

		private float warningAt;

		private int nextRequest;

		private int nextEvent;

		private int lastEvent;

		private float contactDiagnosticAt;

		public static CorePlugin Instance { get; private set; }

		internal string ForcedDraftId => forceDraft.Value;

		public string SessionId => session;

		public int RoundEpoch { get; private set; }

		public bool RoundActive { get; private set; }

		public bool Host
		{
			get
			{
				if (Object.op_Implicit((Object)(object)network) && network.IsListening)
				{
					return network.IsServer;
				}
				return false;
			}
		}

		public bool Racing => CoreGame.IsState((GameState)5);

		public event Action MatchReset;

		public event Action<int> PlayerTeleported;

		public void ContactDiagnostic(string message)
		{
			if (!(Time.unscaledTime < contactDiagnosticAt))
			{
				contactDiagnosticAt = Time.unscaledTime + 3f;
				Note(message);
			}
		}

		public RoundToken CaptureRound()
		{
			return new RoundToken(session, RoundEpoch);
		}

		public bool IsCurrent(RoundToken token)
		{
			return ProtocolRules.IsCurrentRound(RoundActive, session, RoundEpoch, token);
		}

		public static PlayerData Player(int id)
		{
			return CoreGame.Players.FirstOrDefault((Func<PlayerData, bool>)((PlayerData p) => Object.op_Implicit((Object)(object)p) && p.playerIndex.Value == id));
		}

		public void Note(string text)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)text);
		}

		private void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			Instance = this;
			forceDraft = ((BaseUnityPlugin)this).Config.Bind<string>("Testing", "ForceDraftCardId", "", "Host only. Empty disables the override. Set a registered card ID to replace the last native draft offer, without a numeric slot limit. Hidden internal cards are excluded.");
			harmony = new Harmony("slipandskid.extendedcore");
			harmony.PatchAll(typeof(CorePlugin).Assembly);
			Note("Extended Core 1.0.3 ready; no gameplay cards are supplied by Core. [Core JSON serialization hotfix 1]");
		}

		public void RegisterModule(string id, string version)
		{
			if ((Object.op_Implicit((Object)(object)network) && network.IsListening) || (Object.op_Implicit((Object)(object)NetworkManager.Singleton) && NetworkManager.Singleton.IsListening))
			{
				throw new InvalidOperationException("Register modules before entering a network lobby.");
			}
			if (string.IsNullOrWhiteSpace(id) || string.IsNullOrWhiteSpace(version) || id.Length > 128 || version.Length > 64)
			{
				throw new ArgumentException("Stable module ID and protocol version are required.");
			}
			if (modules.TryGetValue(id, out var value))
			{
				if (value != version)
				{
					throw new InvalidOperationException("Conflicting module versions: " + id);
				}
			}
			else
			{
				modules.Add(id, version);
			}
		}

		internal void RequireModule(string id)
		{
			if (id == null || !modules.ContainsKey(id))
			{
				throw new InvalidOperationException("Register the owning module before its cards or channel: " + id);
			}
		}

		public CoreChannel OpenChannel(string module, Action<CoreMessage> hostRequest, Action<CoreMessage> serverEvent, bool requiresRace = true)
		{
			RequireModule(module);
			if (channels.ContainsKey(module))
			{
				throw new InvalidOperationException("Duplicate module channel: " + module);
			}
			CoreChannel coreChannel = new CoreChannel(module, hostRequest, serverEvent, requiresRace);
			channels.Add(module, coreChannel);
			return coreChannel;
		}

		private string Manifest()
		{
			string s = "ExtendedCore/protocol1|" + string.Join("|", from x in modules.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> x) => x.Key, StringComparer.Ordinal)
				select x.Key + "@" + x.Value) + "|" + string.Join("|", CoreCards.Entries.Select((CardHandle h) => h.Id + ":" + h.AffixTag + ":" + h.Definition.ModuleId + ":" + h.Definition.Template.ToString() + ":" + h.Definition.Hidden + ":" + ((object)h.Definition.Rarity/*cast due to .constrained prefix*/).ToString()));
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(s))).Replace("-", "");
		}

		private void Bind()
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if ((!((Object)(object)singleton == (Object)(object)network) || !Object.op_Implicit((Object)(object)singleton) || !singleton.IsListening) && (Object.op_Implicit((Object)(object)network) || (Object.op_Implicit((Object)(object)singleton) && singleton.IsListening)))
			{
				if (Object.op_Implicit((Object)(object)network) && network.CustomMessagingManager != null)
				{
					network.CustomMessagingManager.UnregisterNamedMessageHandler("slipandskid.extendedcore.protocol.v1");
				}
				if (Object.op_Implicit((Object)(object)network))
				{
					network.OnClientDisconnectCallback -= Disconnected;
				}
				network = null;
				session = null;
				peers.Clear();
				requests.Clear();
				acknowledged = false;
				RoundEpoch = 0;
				RoundActive = false;
				wasCountdown = false;
				nextRequest = (nextEvent = (lastEvent = 0));
				CoreCards.Unfreeze();
				this.MatchReset?.Invoke();
				if (Object.op_Implicit((Object)(object)singleton) && singleton.IsListening)
				{
					network = singleton;
					manifest = Manifest();
					CoreCards.Freeze();
					session = (Host ? System.Guid.NewGuid().ToString("N") : null);
					network.CustomMessagingManager.RegisterNamedMessageHandler("slipandskid.extendedcore.protocol.v1", new HandleNamedMessageDelegate(Receive));
					network.OnClientDisconnectCallback += Disconnected;
					helloAt = (stateAt = 0f);
				}
			}
		}

		private void Update()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			CoreCards.EnsureCatalog();
			Bind();
			CoreCards.CompleteModifierPlacements();
			if (!Object.op_Implicit((Object)(object)network) || !CoreGame.TryGetState(out var state))
			{
				return;
			}
			if (!Host && !acknowledged && Time.unscaledTime >= helloAt)
			{
				helloAt = Time.unscaledTime + 1f;
				Send(0uL, new CoreEnvelope
				{
					operation = "hello",
					manifest = manifest
				});
			}
			bool flag = (int)state == 4;
			if (Host)
			{
				if (flag && !wasCountdown)
				{
					RoundEpoch++;
				}
				RoundActive = flag || Racing;
				if (Time.unscaledTime >= stateAt)
				{
					stateAt = Time.unscaledTime + 0.5f;
					foreach (ulong item in network.ConnectedClientsIds.Where((ulong id) => id != network.LocalClientId && peers.Contains(id)))
					{
						SendState(item, "state");
					}
				}
			}
			wasCountdown = flag;
		}

		private void Disconnected(ulong id)
		{
			peers.Remove(id);
			requests.Remove(id);
		}

		public void MatchEnded()
		{
			if (Host)
			{
				RoundEpoch++;
			}
			RoundActive = false;
			wasCountdown = false;
			this.MatchReset?.Invoke();
		}

		public void NotifyTeleported(int player)
		{
			this.PlayerTeleported?.Invoke(player);
		}

		private void Send(ulong id, CoreEnvelope envelope)
		{
			CoreWire.Send(network, "slipandskid.extendedcore.protocol.v1", id, CoreJsonCodec.Serialize(envelope));
		}

		private void SendState(ulong id, string operation)
		{
			Send(id, new CoreEnvelope
			{
				operation = operation,
				session = session,
				manifest = manifest,
				epoch = RoundEpoch,
				active = RoundActive
			});
		}

		internal void Request(CoreChannel channel, CoreMessage message)
		{
			if (!Object.op_Implicit((Object)(object)network) || message == null)
			{
				return;
			}
			if (!Host && !acknowledged)
			{
				if (message.hasContact)
				{
					ContactDiagnostic("Contact request waiting for Core compatibility handshake");
				}
				return;
			}
			CoreEnvelope envelope = new CoreEnvelope
			{
				operation = "request",
				module = channel.Module,
				session = session,
				epoch = RoundEpoch,
				sequence = ++nextRequest,
				message = message
			};
			if (Host)
			{
				DispatchRequest(network.LocalClientId, envelope);
			}
			else
			{
				Send(0uL, envelope);
			}
		}

		internal void Broadcast(CoreChannel channel, CoreMessage message)
		{
			if (!Host || message == null)
			{
				return;
			}
			CoreEnvelope envelope = new CoreEnvelope
			{
				operation = "event",
				module = channel.Module,
				session = session,
				epoch = RoundEpoch,
				sequence = ++nextEvent,
				message = message
			};
			foreach (ulong connectedClientsId in network.ConnectedClientsIds)
			{
				if (connectedClientsId != network.LocalClientId && peers.Contains(connectedClientsId))
				{
					Send(connectedClientsId, envelope);
				}
			}
			channel.ServerEvent?.Invoke(message);
		}

		private void DispatchRequest(ulong sender, CoreEnvelope envelope)
		{
			if (envelope.message != null && envelope.module != null && channels.TryGetValue(envelope.module, out var value))
			{
				PlayerData val = Player(envelope.message.player);
				requests.TryGetValue(sender, out var value2);
				bool ownerMatches = Object.op_Implicit((Object)(object)val) && ((NetworkBehaviour)val).OwnerClientId == sender;
				if (!ProtocolRules.AcceptRequest(sender == network.LocalClientId || peers.Contains(sender), envelope.session == session, envelope.epoch == RoundEpoch, ownerMatches, value.RequiresRace, RoundActive && Racing, envelope.sequence, value2))
				{
					ContactDiagnostic("Core request rejected: module=" + envelope.module + " sender=" + sender + " player=" + envelope.message.player + " owner=" + ownerMatches + " peer=" + peers.Contains(sender) + " session=" + (envelope.session == session) + " epoch=" + envelope.epoch + "/" + RoundEpoch + " racing=" + (RoundActive && Racing));
				}
				else
				{
					requests[sender] = envelope.sequence;
					value.HostRequest?.Invoke(envelope.message);
				}
			}
		}

		private void Receive(ulong sender, FastBufferReader reader)
		{
			try
			{
				if (((FastBufferReader)(ref reader)).Length > 65536)
				{
					return;
				}
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				if (text == null || text.Length > 18000)
				{
					return;
				}
				CoreEnvelope coreEnvelope = (CoreEnvelope)CoreJsonCodec.Deserialize(text, typeof(CoreEnvelope));
				if (coreEnvelope == null)
				{
					return;
				}
				if (Host)
				{
					if (coreEnvelope.operation == "hello")
					{
						if (network.ConnectedClients.ContainsKey(sender))
						{
							if (coreEnvelope.manifest != manifest)
							{
								Send(sender, new CoreEnvelope
								{
									operation = "denied"
								});
							}
							else
							{
								peers.Add(sender);
								SendState(sender, "welcome");
							}
						}
					}
					else if (coreEnvelope.operation == "request")
					{
						DispatchRequest(sender, coreEnvelope);
					}
				}
				else
				{
					if (sender != 0L)
					{
						return;
					}
					if (coreEnvelope.operation == "denied")
					{
						Note("Core compatibility mismatch: every player needs the same gameplay modules and versions.");
					}
					else if (coreEnvelope.operation == "welcome")
					{
						if (!(coreEnvelope.manifest != manifest) && !string.IsNullOrEmpty(coreEnvelope.session))
						{
							if (session != coreEnvelope.session)
							{
								lastEvent = 0;
							}
							session = coreEnvelope.session;
							acknowledged = true;
							RoundEpoch = coreEnvelope.epoch;
							RoundActive = coreEnvelope.active;
						}
					}
					else
					{
						if (!acknowledged || coreEnvelope.session != session)
						{
							return;
						}
						CoreChannel value;
						if (coreEnvelope.operation == "state")
						{
							if (coreEnvelope.epoch >= RoundEpoch)
							{
								RoundEpoch = coreEnvelope.epoch;
								RoundActive = coreEnvelope.active;
							}
						}
						else if (!(coreEnvelope.operation != "event") && coreEnvelope.message != null && ProtocolRules.AcceptEvent(fromServer: true, acknowledged, sessionMatches: true, coreEnvelope.epoch == RoundEpoch, coreEnvelope.sequence, lastEvent) && coreEnvelope.module != null && channels.TryGetValue(coreEnvelope.module, out value))
						{
							lastEvent = coreEnvelope.sequence;
							value.ServerEvent?.Invoke(coreEnvelope.message);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Note("Rejected Core message: " + ex.Message);
			}
		}

		internal bool CanStart()
		{
			if (!Host || modules.Count == 0)
			{
				return true;
			}
			bool num = network.ConnectedClientsIds.All((ulong id) => id == network.LocalClientId || peers.Contains(id));
			if (!num && Time.unscaledTime >= warningAt)
			{
				warningAt = Time.unscaledTime + 5f;
				Note("Waiting for matching Extended Core gameplay modules on every client.");
			}
			return num;
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)network))
			{
				network.OnClientDisconnectCallback -= Disconnected;
			}
			if (Object.op_Implicit((Object)(object)network) && network.CustomMessagingManager != null)
			{
				network.CustomMessagingManager.UnregisterNamedMessageHandler("slipandskid.extendedcore.protocol.v1");
			}
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	public sealed class CoreMaterials : MonoBehaviour
	{
		internal readonly List<Material> owned = new List<Material>();

		private void OnDestroy()
		{
			foreach (Material item in owned)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					Object.Destroy((Object)(object)item);
				}
			}
		}
	}
	public static class CoreVisual
	{
		public static Material Material(Color color)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard"));
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", color);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", color);
			}
			if (color.a < 1f)
			{
				if (val.HasProperty("_Surface"))
				{
					val.SetFloat("_Surface", 1f);
				}
				if (val.HasProperty("_Mode"))
				{
					val.SetFloat("_Mode", 3f);
				}
				val.SetInt("_SrcBlend", 5);
				val.SetInt("_DstBlend", 10);
				val.SetInt("_ZWrite", 0);
				val.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
				val.EnableKeyword("_ALPHABLEND_ON");
				val.renderQueue = 3000;
			}
			return val;
		}

		public static GameObject Shape(PrimitiveType type, string name, Color color, Vector3 scale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.enabled = false;
				Object.Destroy((Object)(object)component);
			}
			obj.transform.localScale = scale;
			Material val = Material(color);
			obj.GetComponent<Renderer>().sharedMaterial = val;
			obj.AddComponent<CoreMaterials>().owned.Add(val);
			return obj;
		}

		public static GameObject Bomb(string name, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			Shape((PrimitiveType)0, "Bomb", color, Vector3.one * 0.8f).transform.SetParent(val.transform, false);
			GameObject obj = Shape((PrimitiveType)2, "Fuse", new Color(1f, 0.8f, 0.2f, color.a), new Vector3(0.08f, 0.15f, 0.08f));
			obj.transform.SetParent(val.transform, false);
			obj.transform.localPosition = new Vector3(0.1f, 0.45f, 0f);
			obj.transform.localRotation = Quaternion.Euler(0f, 0f, -25f);
			GameObject obj2 = Shape((PrimitiveType)0, "Fuse spark", new Color(1f, 0.5f, 0.1f, color.a), Vector3.one * 0.16f);
			obj2.transform.SetParent(val.transform, false);
			obj2.transform.localPosition = new Vector3(0.16f, 0.6f, 0f);
			return val;
		}

		public static GameObject Clone(GameObject source, string name, Color tint, bool recolor = true)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			GameObject val = new GameObject("Chaos clone staging");
			val.SetActive(false);
			GameObject val2 = Object.Instantiate<GameObject>(source, val.transform);
			((Object)val2).name = name;
			MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
			MonoBehaviour[] array = componentsInChildren;
			for (int i = 0; i < array.Length; i++)
			{
				((Behaviour)array[i]).enabled = false;
			}
			foreach (MonoBehaviour item in componentsInChildren.OrderBy((MonoBehaviour b) => (!(b is NetworkObject)) ? ((!(b is Obstacle)) ? 1 : 0) : 2))
			{
				Object.DestroyImmediate((Object)(object)item);
			}
			Animator[] componentsInChildren2 = val2.GetComponentsInChildren<Animator>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Collider[] componentsInChildren3 = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Rigidbody[] componentsInChildren4 = val2.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			AudioSource[] componentsInChildren5 = val2.GetComponentsInChildren<AudioSource>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[i]);
			}
			ParticleSystem[] componentsInChildren6 = val2.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren6.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren6[i]);
			}
			CoreMaterials coreMaterials = val2.AddComponent<CoreMaterials>();
			Renderer[] componentsInChildren7 = val2.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren7)
			{
				if (recolor)
				{
					Material[] collection = (val3.sharedMaterials = val3.sharedMaterials.Select((Material m) => Material(tint)).ToArray());
					coreMaterials.owned.AddRange(collection);
				}
				val3.enabled = true;
			}
			val2.transform.SetParent((Transform)null, false);
			val2.SetActive(true);
			Object.Destroy((Object)(object)val);
			return val2;
		}

		public static GameObject Line(Vector3 a, Vector3 b, Color color, float width)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Shape((PrimitiveType)3, "Chaos line", color, Vector3.one);
			PositionLine(obj, a, b, width);
			return obj;
		}

		public static void PositionLine(GameObject line, Vector3 a, Vector3 b, float width)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			line.transform.position = (a + b) * 0.5f;
			line.transform.rotation = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(val) : Quaternion.identity);
			line.transform.localScale = new Vector3(width, width, ((Vector3)(ref val)).magnitude);
		}

		public static void Pulse(Vector3 position, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Shape((PrimitiveType)0, "Chaos pulse", new Color(color.r, color.g, color.b, 0.4f), Vector3.one * 2f);
			obj.transform.position = position;
			Object.Destroy((Object)(object)obj, 0.3f);
		}
	}
	public readonly struct RoundToken
	{
		public string Session { get; }

		public int Epoch { get; }

		public RoundToken(string session, int epoch)
		{
			Session = session;
			Epoch = epoch;
		}
	}
	public static class ProtocolRules
	{
		public static bool IsCurrentRound(bool active, string session, int epoch, RoundToken token)
		{
			if (active && !string.IsNullOrEmpty(session) && session == token.Session)
			{
				return epoch == token.Epoch;
			}
			return false;
		}

		public static bool AcceptRequest(bool peerReady, bool sessionMatches, bool epochMatches, bool ownerMatches, bool raceRequired, bool racing, int sequence, int previous)
		{
			if (peerReady && sessionMatches && epochMatches && ownerMatches && (!raceRequired || racing))
			{
				return sequence > previous;
			}
			return false;
		}

		public static bool AcceptEvent(bool fromServer, bool acknowledged, bool sessionMatches, bool epochMatches, int sequence, int previous)
		{
			if (fromServer && acknowledged && sessionMatches && epochMatches)
			{
				return sequence > previous;
			}
			return false;
		}
	}
	public sealed class RegistrationTable<T>
	{
		private readonly Dictionary<string, T> ids = new Dictionary<string, T>(StringComparer.Ordinal);

		private readonly Dictionary<string, int> tags = new Dictionary<string, int>(StringComparer.Ordinal);

		private readonly Dictionary<int, string> owners = new Dictionary<int, string>();

		public bool Frozen { get; private set; }

		public int Count => ids.Count;

		public IEnumerable<string> Ids => ids.Keys.OrderBy<string, string>((string x) => x, StringComparer.Ordinal);

		public int Add(string id, T value, int? legacyTag = null)
		{
			if (Frozen)
			{
				throw new InvalidOperationException("Register cards before joining a lobby; restart to change the card set.");
			}
			if (string.IsNullOrWhiteSpace(id) || id.Length > 160)
			{
				throw new ArgumentException("Use a stable, nonempty card ID of at most 160 characters.", "id");
			}
			if (ids.ContainsKey(id))
			{
				throw new InvalidOperationException("Duplicate card ID: " + id);
			}
			int num = legacyTag ?? StableTag(id);
			if (num >= 0)
			{
				throw new ArgumentException("Custom card tags must be negative.");
			}
			if (owners.TryGetValue(num, out var value2))
			{
				throw new InvalidOperationException("Card tag collision: " + id + " / " + value2 + ". Supply an explicit unused negative tag.");
			}
			ids.Add(id, value);
			tags.Add(id, num);
			owners.Add(num, id);
			return num;
		}

		public bool TryGet(string id, out T value)
		{
			return ids.TryGetValue(id, out value);
		}

		public bool TryGet(int tag, out T value)
		{
			if (owners.TryGetValue(tag, out var value2))
			{
				return ids.TryGetValue(value2, out value);
			}
			value = default(T);
			return false;
		}

		public int Tag(string id)
		{
			return tags[id];
		}

		public void Freeze()
		{
			Frozen = true;
		}

		public void Unfreeze()
		{
			Frozen = false;
		}

		public static int StableTag(string id)
		{
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(id));
			uint num = (uint)((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]);
			return -2000000 - (int)(num % 1000000000);
		}
	}
}
namespace SlipAndSkid.ExtendedCore.Audio
{
	public sealed class PcmWave
	{
		public float[] samples;

		public int channels;

		public int rate;

		public static PcmWave Decode(byte[] bytes)
		{
			using MemoryStream memoryStream = new MemoryStream(bytes, writable: false);
			using BinaryReader binaryReader = new BinaryReader(memoryStream);
			if (bytes.Length < 12 || Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "RIFF")
			{
				throw new InvalidDataException("Expected RIFF WAV");
			}
			uint num = binaryReader.ReadUInt32();
			if ((long)num + 8L > bytes.Length)
			{
				throw new InvalidDataException("Truncated WAV");
			}
			long num2 = (long)num + 8L;
			if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "WAVE")
			{
				throw new InvalidDataException("Expected WAV header");
			}
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			byte[] array = null;
			while (memoryStream.Position + 8 <= num2)
			{
				string text = Encoding.ASCII.GetString(binaryReader.ReadBytes(4));
				uint num6 = binaryReader.ReadUInt32();
				long num7 = memoryStream.Position + num6 + (num6 & 1);
				if (num7 > num2 || num6 > int.MaxValue)
				{
					throw new InvalidDataException("Truncated WAV chunk");
				}
				if (text == "fmt ")
				{
					if (num6 < 16 || binaryReader.ReadUInt16() != 1)
					{
						throw new InvalidDataException("Use PCM 16-bit WAV");
					}
					num3 = binaryReader.ReadUInt16();
					num4 = binaryReader.ReadInt32();
					binaryReader.ReadUInt32();
					num5 = binaryReader.ReadUInt16();
					int num8 = binaryReader.ReadUInt16();
					if ((num3 != 1 && num3 != 2) || num4 < 8000 || num4 > 192000 || num8 != 16 || num5 != num3 * 2)
					{
						throw new InvalidDataException("Use mono/stereo PCM 16-bit WAV");
					}
				}
				else if (text == "data")
				{
					array = binaryReader.ReadBytes((int)num6);
				}
				memoryStream.Position = num7;
			}
			if (num3 == 0 || array == null || array.Length == 0 || array.Length % num5 != 0)
			{
				throw new InvalidDataException("Missing or incomplete WAV samples");
			}
			PcmWave pcmWave = new PcmWave
			{
				channels = num3,
				rate = num4,
				samples = new float[array.Length / 2]
			};
			for (int i = 0; i < pcmWave.samples.Length; i++)
			{
				pcmWave.samples[i] = (float)(short)(array[i * 2] | (array[i * 2 + 1] << 8)) / 32768f;
			}
			return pcmWave;
		}
	}
}
namespace SlipAndSkid.ExtendedCore
{
	internal static class CoreJsonCodec
	{
		public static string Serialize(object value)
		{
			if (value == null)
			{
				throw new ArgumentNullException("value");
			}
			return Write(value, 0).ToString((Formatting)0, Array.Empty<JsonConverter>());
		}

		public static object Deserialize(string json, Type type)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if (json == null || json.Length > 18000)
			{
				throw new ArgumentException("Invalid Core JSON length");
			}
			JToken val = JToken.Parse(json);
			if ((int)val.Type != 1)
			{
				throw new ArgumentException("Core envelope must be an object");
			}
			return Read(val, type, 0);
		}

		private static JToken Write(object value, int depth)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			if (depth > 8)
			{
				throw new ArgumentException("Core message nesting is too deep");
			}
			if (value == null)
			{
				return (JToken)(object)JValue.CreateNull();
			}
			Type type = value.GetType();
			if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal))
			{
				return (JToken)new JValue(value);
			}
			JObject val = new JObject();
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				val.Add(fieldInfo.Name, Write(fieldInfo.GetValue(value), depth + 1));
			}
			return (JToken)(object)val;
		}

		private static object Read(JToken token, Type type, int depth)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			if (depth > 8)
			{
				throw new ArgumentException("Core message nesting is too deep");
			}
			if ((int)token.Type == 10)
			{
				if (type.IsValueType)
				{
					throw new ArgumentException("Null Core value");
				}
				return null;
			}
			if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal))
			{
				if (!(token is JValue))
				{
					throw new ArgumentException("Expected primitive Core value");
				}
				return token.ToObject(type);
			}
			JObject val = (JObject)(object)((token is JObject) ? token : null);
			if (val == null)
			{
				throw new ArgumentException("Expected Core object");
			}
			object obj = Activator.CreateInstance(type, nonPublic: true);
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			JToken token2 = default(JToken);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (val.TryGetValue(fieldInfo.Name, StringComparison.Ordinal, ref token2))
				{
					fieldInfo.SetValue(obj, Read(token2, fieldInfo.FieldType, depth + 1));
				}
			}
			if (type.FullName == "SlipAndSkid.ExtendedCore.CoreEnvelope")
			{
				string text = (string)val["operation"];
				if (text == "request" || text == "event")
				{
					JToken obj2 = val["message"];
					JObject val2 = (JObject)(object)((obj2 is JObject) ? obj2 : null);
					if (val2 == null || val2["kind"] == null || val2["player"] == null || val2["objectId"] == null)
					{
						throw new ArgumentException("Core gameplay message is missing required fields");
					}
				}
			}
			return obj;
		}
	}
}