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;
}
}
}