Decompiled source of Toozys Minigames Client v1.2.0
BepInEx/plugins/Toozy-Minigames/Toozy.PeakMinigames.Client.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Peak.Afflictions; using PeakKoth.Authoring; using Photon.Pun; using Photon.Realtime; using TMPro; using Toozy.PeakMinigames; using Toozy.ReplayIntegration; using UnityEngine; using UnityEngine.Animations.Rigging; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Toozy.PeakMinigames.Client")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("Toozy.PeakMinigames.Client")] [assembly: AssemblyTitle("Toozy.PeakMinigames.Client")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PeakKoth.Authoring { public static class KothSurfaceBinding { public const string MarkerName = "__KOTH_UnclimbableSurface_v1"; public static int Apply(GameObject[] roots, int mapLayer) { if (mapLayer < 0 || mapLayer > 31) { throw new InvalidOperationException("PEAK's Map layer is missing."); } int num = 0; foreach (Transform item in roots.SelectMany((GameObject g) => g.GetComponentsInChildren<Transform>(true))) { bool flag = ((IEnumerable)item).Cast<Transform>().Any((Transform child) => ((Object)child).name == "__KOTH_UnclimbableSurface_v1"); ((Component)item).gameObject.layer = ((!flag) ? mapLayer : 0); if (flag) { num++; } } return num; } } public static class KothHillGeometry { public const string MarkerName = "__KOTH_HillZone_v1"; public static bool Valid(Vector3 size) { //IL_0000: 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_0015: 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) if (Finite(size) && size.x > 0f && size.y > 0f) { return size.z > 0f; } return false; } public static bool Finite(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.x) && !float.IsInfinity(v.y)) { return !float.IsInfinity(v.z); } return false; } public static bool Contains(BoxCollider box, Vector3 world) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)box == (Object)null || !((Component)box).gameObject.activeInHierarchy || !Finite(world)) { return false; } Vector3 val = ((Component)box).transform.InverseTransformPoint(world) - box.center; Vector3 val2 = box.size * 0.5f; if (Finite(val) && Mathf.Abs(val.x) <= val2.x && Mathf.Abs(val.y) <= val2.y) { return Mathf.Abs(val.z) <= val2.z; } return false; } } [Serializable] public sealed class KothChestDefinition { public const string MarkerPrefix = "__KOTH_Chest_v1:"; public const int MaxChests = 64; public int schema = 1; public int itemCount = 2; public float rechargeSeconds; public float openSeconds = 1.5f; public bool startsReady = true; public string itemIds = ""; public bool Valid() { if (schema == 1 && itemCount >= 1 && itemCount <= 4 && Finite(rechargeSeconds) && (rechargeSeconds == 0f || (rechargeSeconds >= 5f && rechargeSeconds <= 600f)) && Finite(openSeconds) && openSeconds >= 0.5f && openSeconds <= 10f && itemIds != null && itemIds.Length <= 1024) { ushort result; if (itemIds.Trim().Length != 0) { return itemIds.Split(',').All((string s) => ushort.TryParse(s.Trim(), out result)); } return true; } return false; } private static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } } public static class KothChestGeometry { public static Vector3 RestOffset(Renderer[] renderers, Vector3 floor, Quaternion rotation) { //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_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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Quaternion.Inverse(rotation); Vector3 val2 = Vector3.one * float.PositiveInfinity; Vector3 val3 = Vector3.one * float.NegativeInfinity; foreach (Renderer val4 in renderers) { if (val4 is MeshRenderer || val4 is SkinnedMeshRenderer) { Bounds localBounds = val4.localBounds; for (int j = 0; j < 8; j++) { Vector3 val5 = ((Bounds)(ref localBounds)).center + Vector3.Scale(((Bounds)(ref localBounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1)))); Vector3 val6 = val * (((Component)val4).transform.TransformPoint(val5) - floor); val2 = Vector3.Min(val2, val6); val3 = Vector3.Max(val3, val6); } } } if (!float.IsInfinity(val2.y)) { return -(rotation * new Vector3((val2.x + val3.x) * 0.5f, val2.y, (val2.z + val3.z) * 0.5f)); } return Vector3.zero; } public static void PlaceLootPoints(Transform root) { //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0095: Unknown result type (might be due to invalid IL or missing references) float floor; Bounds val = TrayBounds(root, out floor); Transform val2 = root.Find("LootPoints"); Vector3 val3 = default(Vector3); for (int i = 0; i < val2.childCount; i++) { ((Vector3)(ref val3))..ctor(((Bounds)(ref val)).center.x + ((i % 2 == 0) ? (-0.25f) : 0.25f) * ((Bounds)(ref val)).size.x, floor, ((Bounds)(ref val)).center.z + ((i < 2) ? (-0.22f) : 0.22f) * ((Bounds)(ref val)).size.z); val2.GetChild(i).position = root.TransformPoint(val3); val2.GetChild(i).rotation = root.rotation; } } public static Bounds TrayBounds(Transform root, out float floor) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) Transform val = root.Find("Visual/LuggageSmall/luggage"); Mesh sharedMesh = ((Component)val).GetComponent<MeshFilter>().sharedMesh; Vector3[] vertices = sharedMesh.vertices; for (int i = 0; i < vertices.Length; i++) { vertices[i] = root.InverseTransformPoint(val.TransformPoint(vertices[i])); } Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(vertices[0], Vector3.zero); Vector3[] array = vertices; foreach (Vector3 val2 in array) { ((Bounds)(ref result)).Encapsulate(val2); } int[] triangles = sharedMesh.triangles; float num = 0f; floor = ((Bounds)(ref result)).center.y; for (int k = 0; k < triangles.Length; k += 3) { Vector3 val3 = vertices[triangles[k]]; Vector3 val4 = vertices[triangles[k + 1]]; Vector3 val5 = vertices[triangles[k + 2]]; Vector3 val6 = Vector3.Cross(val4 - val3, val5 - val3); if (((Vector3)(ref val6)).normalized.y > 0.95f && ((Vector3)(ref val6)).sqrMagnitude > num) { num = ((Vector3)(ref val6)).sqrMagnitude; floor = (val3.y + val4.y + val5.y) / 3f; } } if (num == 0f) { throw new InvalidOperationException("Chest tray has no upward floor surface."); } return result; } } } namespace Toozy.ReplayIntegration { internal sealed class ReplayConnection { internal delegate bool Clock(out string path, out double seconds); internal delegate bool Viewer(out string path, out double seconds, out int track, out string identity, out string name, out Vector3 position, out bool hud, out bool effects, out bool pov, out RectTransform? stamina, out RectTransform? inventory); internal Clock? Recording; internal Clock? Playback; internal Viewer? View; internal Func<bool>? Active; internal Action<string>? Status; internal Action<string>? Warning; internal Action<string>? Unregister; internal Action<string, Func<string, string>, Func<string, IEnumerator>>? Register; internal Action<string>? ContinueAfterScene; internal Action<string>? ResumeAfterScene; private double nextSearch; internal bool Connected => Recording != null; internal void Discover() { if (Connected || Time.unscaledTimeAsDouble < nextSearch) { return; } nextSearch = Time.unscaledTimeAsDouble + 2.0; foreach (PluginInfo value in Chainloader.PluginInfos.Values) { BaseUnityPlugin p; Type type; if (!((Object)(object)value.Instance == (Object)null) && !(((object)value.Instance).GetType().FullName != "PeakReplay.Plugin")) { p = value.Instance; type = ((object)p).GetType(); Playback = Bind<Clock>("GetMinigamePlaybackV1"); View = Bind<Viewer>("GetMinigameReplayViewV1"); Active = Bind<Func<bool>>("IsMinigameReplayViewActiveV1"); Status = Bind<Action<string>>("ReportMinigameReplayStatusV1"); Warning = Bind<Action<string>>("ReportMinigameCaptureFailureV1"); Register = Bind<Action<string, Func<string, string>, Func<string, IEnumerator>>>("RegisterMinigameSceneV1"); Unregister = Bind<Action<string>>("UnregisterMinigameSceneV1"); ContinueAfterScene = Bind<Action<string>>("ContinueMinigameRecordingAfterSceneLoadV1"); ResumeAfterScene = Bind<Action<string>>("ResumeMinigameRecordingAfterSceneLoadV1"); Recording = Bind<Clock>("GetMinigameRecordingV1"); break; } T? Bind<T>(string name) where T : notnull, Delegate { MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public); if (!(method == null)) { return (T)Delegate.CreateDelegate(typeof(T), p, method); } return null; } } } } internal sealed class ReplayJournal : IDisposable { private sealed class Fields : DefaultContractResolver { protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization ignored) { List<JsonProperty> list = new List<JsonProperty>(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { list.Add(((DefaultContractResolver)this).CreateProperty((MemberInfo)fieldInfo, (MemberSerialization)2)); } return list; } } private readonly BlockingCollection<string> queue = new BlockingCollection<string>(512); internal readonly Task Completion; internal volatile Exception? Error; internal static readonly JsonSerializerSettings Json = new JsonSerializerSettings { ContractResolver = (IContractResolver)(object)new Fields(), TypeNameHandling = (TypeNameHandling)0, MetadataPropertyHandling = (MetadataPropertyHandling)2, ObjectCreationHandling = (ObjectCreationHandling)2, MaxDepth = 24, CheckAdditionalContent = true, NullValueHandling = (NullValueHandling)1 }; internal ReplayJournal(string path) { ReplayJournal replayJournal = this; Completion = Task.Run(delegate { try { using FileStream stream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.Read); using StreamWriter streamWriter = new StreamWriter(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), 65536); foreach (string item in replayJournal.queue.GetConsumingEnumerable()) { streamWriter.WriteLine(item); if (replayJournal.queue.Count == 0) { streamWriter.Flush(); } } } catch (Exception error) { replayJournal.Error = error; } }); } internal bool Write<T>(T value) { if (Error == null && !queue.IsAddingCompleted) { return queue.TryAdd(JsonConvert.SerializeObject((object)value, Json)); } return false; } public void Dispose() { if (!queue.IsAddingCompleted) { queue.CompleteAdding(); } } internal static bool Finite(double v) { if (!double.IsNaN(v)) { return !double.IsInfinity(v); } return false; } internal static IEnumerable<T> Read<T>(string path) { if (!File.Exists(path)) { yield break; } if (new FileInfo(path).Length > 536870912) { throw new InvalidDataException("Minigame sidecar exceeds 512 MB."); } using StreamReader reader = new StreamReader(path); int count = 0; string text; while ((text = reader.ReadLine()) != null) { if (text.Length <= 262144) { int num = count + 1; count = num; if (num <= 2000000) { T val; try { val = JsonConvert.DeserializeObject<T>(text, Json); } catch (JsonException) { if (reader.EndOfStream) { break; } throw; } if (val != null) { yield return val; } continue; } } throw new InvalidDataException("Minigame sidecar exceeds event limits."); } } } } namespace Toozy.PeakKoth { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("toozy.peak.koth", "Toozy KOTH Loader", "1.2.0")] [DefaultExecutionOrder(10000)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(AchievementManager), "AddToRunBasedFloat")] private static class ArenaMissingFloatStatsPatch { private static bool Prefix(AchievementManager __instance) { return !MissingArenaAchievementStats(__instance); } } [HarmonyPatch(typeof(AchievementManager), "AddToRunBasedInt")] private static class ArenaMissingIntStatsPatch { private static bool Prefix(AchievementManager __instance) { return !MissingArenaAchievementStats(__instance); } } [HarmonyPatch(typeof(AchievementManager), "RecordMaxHeight")] private static class ArenaMissingHeightStatsPatch { private static bool Prefix(AchievementManager __instance) { return !MissingArenaAchievementStats(__instance); } } [HarmonyPatch(typeof(GUIManager), "LateUpdate")] private static class ChestHoverTextPatch { private static void Postfix(GUIManager __instance) { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner != null && survivalOwner.ChestActionsActive && !((Object)(object)Interaction.instance == (Object)null) && Interaction.instance.currentHovered is ArenaChest arenaChest && !((Object)(object)arenaChest == (Object)null)) { if ((Object)(object)__instance.interactNameText != (Object)null) { ((TMP_Text)__instance.interactNameText).text = arenaChest.GetName(); } if ((Object)(object)__instance.interactPromptText != (Object)null) { ((TMP_Text)__instance.interactPromptText).text = arenaChest.GetInteractionText(); } } } } private sealed class PendingItemAttachment { internal Item item; internal Collider[] colliders = Array.Empty<Collider>(); internal bool[] enabled = Array.Empty<bool>(); internal Coroutine? routine; internal void RestoreColliders() { for (int i = 0; i < colliders.Length; i++) { if ((Object)(object)colliders[i] != (Object)null) { colliders[i].enabled = enabled[i]; } } } } [HarmonyPatch(typeof(CharacterItems), "Equip")] private static class ArenaEquipPatch { private static bool Prefix(CharacterItems __instance, Character ___character, Item item, ref Item __result) { if (!ArenaSurvivalApplies(___character)) { return true; } __result = ___character.data.currentItem; survivalOwner.EquipArenaItem(__instance, ___character, item); return false; } } [HarmonyPatch(typeof(CharacterItems), "UnAttachItem")] private static class ArenaDetachPatch { private static bool Prefix(CharacterItems __instance, Character ___character) { if (!ArenaSurvivalApplies(___character)) { return true; } survivalOwner.CancelPendingAttachment(__instance); DetachArenaHands(___character); return false; } } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")] private static class ArenaReviveCampaignRecordPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo original = AccessTools.Method(typeof(ReconnectHandler), "UpdateFromRevive", (Type[])null, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(ArenaReviveCampaignRecordPatch), "RecordCampaignRevive", (Type[])null, (Type[])null); int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, original)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; replaced++; } yield return instruction; } if (replaced != 1) { throw new InvalidOperationException("Native revive bookkeeping changed; expected one reconnect record call."); } } private static void RecordCampaignRevive(ReconnectHandler handler, Character character, Vector3 position) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!ArenaSurvivalApplies(character)) { handler.UpdateFromRevive(character, position); } } } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")] private static class ArenaRevivedPatch { private static void Postfix(Character __instance) { if (ArenaSurvivalApplies(__instance)) { __instance.data.zombified = false; if (__instance.IsLocal && ((MonoBehaviourPun)__instance).photonView.IsMine) { survivalOwner.CancelPendingAttachment(__instance.refs.items); survivalOwner.CancelLocalPush(); survivalOwner.EndShove(); __instance.data.currentStamina = 1f; __instance.refs.movement.CapFallDamage(0f, 3f); } } } } [HarmonyPatch(typeof(Character), "CheckEndGame")] private static class ArenaAllDeadPatch { private static bool Prefix() { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner == null) { return true; } return !survivalOwner.OwnsArenaEnding; } } [HarmonyPatch(typeof(Character), "RPCEndGame")] private static class ArenaNativeEndPatch { private static bool Prefix() { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner == null) { return true; } return !survivalOwner.OwnsArenaEnding; } } [HarmonyPatch] private static class ArenaFallDamageContextPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(CharacterMovement), "CheckFallDamage", Type.EmptyTypes, (Type[])null) ?? throw new MissingMethodException("CharacterMovement.CheckFallDamage"); yield return AccessTools.Method(typeof(CharacterClimbing), "CheckFallDamage", new Type[1] { typeof(RaycastHit) }, (Type[])null) ?? throw new MissingMethodException("CharacterClimbing.CheckFallDamage"); } private static void Prefix(Character ___character, out Character? __state) { __state = fallDamageCharacter; fallDamageCharacter = ___character; } private static Exception? Finalizer(Exception? __exception, Character? __state) { fallDamageCharacter = __state; return __exception; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")] private static class ArenaAddedStatusPatch { private static bool Prefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref bool __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!ArenaSurvivalApplies(__instance.character)) { return true; } if ((int)statusType != 1 && ((int)statusType != 0 || fallDamageCharacter != __instance.character)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "get_canGetHungry")] private static class ArenaHungerEligibilityPatch { private static bool Prefix(CharacterAfflictions __instance, ref bool __result) { if (!ArenaSurvivalApplies(__instance.character)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "SetStatus")] private static class ArenaSetHungerPatch { private static void Prefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)statusType == 1 && ArenaSurvivalApplies(__instance.character)) { amount = 0f; } } } private sealed class KothReplayFrame { internal KothReplayState State; internal double Time; internal double ScoreAge; internal int Actor; internal bool Hud; internal bool Effects; internal float Blur; internal float Charge; internal bool Charging; internal RectTransform? Inventory; } private sealed class ReplayChestBinding { internal Transform[] Nodes = Array.Empty<Transform>(); internal string[] Paths = Array.Empty<string>(); internal float[] Last = Array.Empty<float>(); internal float[] Scratch = Array.Empty<float>(); internal double LastSample; internal double LastWritten = -1.0; internal Animator? Animator; internal bool AnimatorEnabled; } private sealed class ReplayLease { internal string Nonce = ""; internal double Until; } private sealed class RemoteReplayView { internal KothReplayPrivate View; internal double Received; internal long Sequence; } [HarmonyPatch(typeof(CharacterGrabbing), "Update")] private static class ArenaReachCleanupPatch { private static void Prefix(Character ___character) { Plugin survivalOwner = Plugin.survivalOwner; if (!((Object)(object)survivalOwner == (Object)null) && ArenaSurvivalApplies(___character) && ___character.IsLocal && (survivalOwner.RoundActionsActive || survivalOwner.RoundInputLocked)) { if (___character.data.isReaching || Object.op_Implicit((Object)(object)___character.data.grabJoint)) { ((MonoBehaviourPun)___character).photonView.RPC("RPCA_StopReaching", (RpcTarget)0, Array.Empty<object>()); } if (survivalOwner.RoundInputLocked) { ___character.data.sincePressReach = 100f; } } } } [HarmonyPatch(typeof(CharacterGrabbing), "get_isKickMode")] private static class ArenaNativeKickPatch { private static void Postfix(CharacterGrabbing __instance, ref bool __result) { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner != null && survivalOwner.PushSessionActive && ArenaSurvivalApplies(((Component)__instance).GetComponent<Character>())) { __result = Plugin.survivalOwner.RoundActionsActive; } } } [HarmonyPatch(typeof(CharacterAnimations), "HandleIK")] private static class PushHandWeightsPatch { private static void Postfix(Character ___character) { survivalOwner?.ApplyPushHands(___character, targets: false); } } [HarmonyPatch(typeof(CharacterAnimations), "ConfigureIK")] private static class PushHandTargetsPatch { private static void Postfix(Character ___character) { survivalOwner?.ApplyPushHands(___character, targets: true); } } [HarmonyPatch(typeof(CharacterInput), "Sample")] private static class RoundInputPatch { private static void Postfix(CharacterInput __instance) { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner != null && survivalOwner.FreezeApplies(((Component)__instance).GetComponent<Character>())) { BlockRoundInput(__instance); } } } [HarmonyPatch(typeof(Character), "CheckJump")] private static class RoundJumpPatch { private static void Postfix(Character __instance, ref bool __result) { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner != null && survivalOwner.FreezeApplies(__instance)) { __result = false; } } } [HarmonyPatch(typeof(CharacterClimbing), "CanClimb")] private static class RoundClimbPatch { private static void Postfix(CharacterClimbing __instance, ref bool __result) { Plugin? survivalOwner = Plugin.survivalOwner; if (survivalOwner != null && survivalOwner.FreezeApplies(((Component)__instance).GetComponent<Character>())) { __result = false; } } } private static readonly StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, float>> RunFloatCounters = AccessTools.StructFieldRefAccess<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, float>>("runBasedFloats"); private static readonly StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, int>> RunIntCounters = AccessTools.StructFieldRefAccess<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, int>>("runBasedInts"); private const byte ChestIntentEvent = 192; private const byte ChestStateEvent = 193; private readonly List<ArenaChest> arenaChests = new List<ArenaChest>(); private AnimatorOverrideController? chestAnimation; private readonly List<AnimationClip> chestClips = new List<AnimationClip>(); private long chestInputSequence; private long chestStateSequence; private readonly Dictionary<CharacterItems, PendingItemAttachment> pendingItemAttachments = new Dictionary<CharacterItems, PendingItemAttachment>(); private static readonly Func<CharacterItems, Item, Quaternion> NativeHoldRotation = (Func<CharacterItems, Item, Quaternion>)AccessTools.Method(typeof(CharacterItems), "GetItemHoldRotation", (Type[])null, (Type[])null).CreateDelegate(typeof(Func<CharacterItems, Item, Quaternion>)); private static readonly Action<CharacterItems, Item> NativeAttachItem = (Action<CharacterItems, Item>)AccessTools.Method(typeof(CharacterItems), "AttachItem", (Type[])null, (Type[])null).CreateDelegate(typeof(Action<CharacterItems, Item>)); private static readonly Action<Item, ItemState, Character> NativeItemState = (Action<Item, ItemState, Character>)AccessTools.Method(typeof(Item), "SetState", new Type[2] { typeof(ItemState), typeof(Character) }, (Type[])null).CreateDelegate(typeof(Action<Item, ItemState, Character>)); private static readonly Action<Item, Vector3, Quaternion> NativeMoveItem = (Action<Item, Vector3, Quaternion>)AccessTools.Method(typeof(Item), "Move", new Type[2] { typeof(Vector3), typeof(Quaternion) }, (Type[])null).CreateDelegate(typeof(Action<Item, Vector3, Quaternion>)); private ArenaLighting? arenaLighting; private ConfigEntry<float> arenaSunIntensity; private ConfigEntry<float> arenaShadowFill; private Transform[] arenaSpawnPoints = Array.Empty<Transform>(); private readonly Dictionary<int, int> lastArenaSpawn = new Dictionary<int, int>(); private Harmony? survivalHarmony; private static Plugin? survivalOwner; [ThreadStatic] private static Character? fallDamageCharacter; private Character? shovedCharacter; private Vector3 shoveDirection; private Vector3 shoveOrigin; private float shovePeak; private float shoveElapsed; private float shoveBaseline; private float shoveLimit; private const byte PushIntentEvent = 190; private const byte PushResultEvent = 191; private ConfigEntry<KeyCode> pushKey; private bool pushCharging; private double pushStarted; private double nextPushHeartbeat; private double localPushReady; private double pushNoticeUntil; private long pushInputSequence; private long localChargeId; private long lastPushResultSequence; private long releasedChargeId; private string pushNotice = ""; private const string CatalogObjectName = "KOTH_Customization"; private const byte HillScoreEvent = 189; private BoxCollider? hillZone; private HillScorePacket? hillScores; private double lastHillReceived; private readonly ReplayConnection replay = new ReplayConnection(); private ReplayJournal? replayWriter; private ReplayJournal? lastReplayWriter; private string? replayRecordPath; private string? replayClosedPath; private string? replayLoadPath; private Task<KothReplayTimeline>? replayLoad; private Task? replayArchive; private readonly Dictionary<string, Task> replayArchives = new Dictionary<string, Task>(); private KothReplayTimeline? replayTimeline; private KothReplayHeader? replayHeader; private readonly Dictionary<int, KothReplayPerson> replayPeople = new Dictionary<int, KothReplayPerson>(); private string replayStateSignature = ""; private double nextReplaySample; private double nextReplayState; private bool replayRegistered; private bool replayWasActive; private bool replayArena; private KothReplayFrame? replayFrame; private readonly List<ReplayChestBinding> captureChests = new List<ReplayChestBinding>(); private readonly List<ReplayChestBinding> playbackChests = new List<ReplayChestBinding>(); private string? replayBundlePath; private bool replayLoadingArena; private const byte ReplayTelemetryEvent = 177; private string replayNonce = ""; private double nextReplayRequest; private double nextReplaySend; private long replaySendSequence; private KothReplayPrivate? lastSentReplayView; private double lastReplaySendAt; private readonly Dictionary<int, ReplayLease> replayLeases = new Dictionary<int, ReplayLease>(); private readonly Dictionary<int, RemoteReplayView> remoteReplayViews = new Dictionary<int, RemoteReplayView>(); private readonly Dictionary<int, double> replayReceiveGate = new Dictionary<int, double>(); private readonly Dictionary<int, double> capturedViews = new Dictionary<int, double>(); private readonly Dictionary<int, KothReplayPrivate> capturedViewStates = new Dictionary<int, KothReplayPrivate>(); private bool legacyPushPatched; private static FieldInfo? legacyCharging; private static FieldInfo? legacyChargeBar; private TeamLobbyState teamLobby = new TeamLobbyState(); private string teamLobbyJson = ""; private KothTeamFlagVisual? teamFlags; private const byte SessionEvent = 188; private const string VersionProperty = "koth.version"; private const string HashProperty = "koth.map"; private const string HostProperty = "koth.host"; private const string ReadyProperty = "koth.ready"; private string mapHash = ""; private Room? lobby; private SessionPacket? session; private string preparedToken = ""; private string loadedToken = ""; private string returnedToken = ""; private bool savedAutoSync; private bool ownsAutoSync; private bool orphaned; private float phaseDeadline; private float nextNetworkTick; private readonly HashSet<string> endedTokens = new HashSet<string>(); public const string RoleName = "CLIENT - SHARE"; private const bool HasHostEngine = false; private static readonly Func<Character, float, bool, bool, bool> NativeUseStamina = (Func<Character, float, bool, bool, bool>)AccessTools.Method(typeof(Character), "UseStamina", new Type[3] { typeof(float), typeof(bool), typeof(bool) }, (Type[])null).CreateDelegate(typeof(Func<Character, float, bool, bool, bool>)); private GameObject? pushMeterCanvas; private Image? nativePushFill; private readonly Dictionary<int, float> pushAnimations = new Dictionary<int, float>(); private GameObject? roundBlurObject; private Volume? roundBlurVolume; private VolumeProfile? roundBlurProfile; private static readonly FieldInfo PressedDrop = AccessTools.Field(typeof(CharacterItems), "pressedDrop"); private GameObject? arenaUi; private GameObject? arenaHud; private GameObject? settingsBlockerObject; private GameObject? settingsOverlay; private MenuWindow? settingsBlocker; private RectTransform? uiSafeArea; private TMP_FontAsset? arenaFont; private TMP_FontAsset? arenaNumberFont; private readonly List<Material> arenaTextMaterials = new List<Material>(); private TextMeshProUGUI? timerText; private TextMeshProUGUI? roundRuleText; private TextMeshProUGUI? resultText; private TextMeshProUGUI? boardText; private TextMeshProUGUI? giftText; private TextMeshProUGUI? boardRanks; private TextMeshProUGUI? boardPoints; private TextMeshProUGUI? finalRanks; private TextMeshProUGUI? finalNames; private TextMeshProUGUI? finalPoints; private TextMeshProUGUI? readyNumber; private TextMeshProUGUI? readyLabel; private GameObject? liveStandings; private GameObject? finalStandings; private readonly Vector3[] inventoryCorners = (Vector3[])(object)new Vector3[4]; private bool settingsOpen; private float nextUiRefresh; public const string Id = "toozy.peak.koth"; public const string Version = "1.2.0"; public const string LevelName = "Level_KOTH"; private AssetBundle? levelBundle; private GameObject? bootstrapCache; private readonly Dictionary<string, Shader> nativeShaders = new Dictionary<string, Shader>(); private readonly List<Material> materials = new List<Material>(); private bool transitioning; private bool initialized; private string pendingVisibleReady = ""; private Exception? loadFailure; private Room? testRoom; private bool roomWasOpen; private Vector3 spawnPosition; private float nextRecovery; private float recoveryFloorY; private int previousCharacterId; private string status = "Waiting for the airport lobby..."; private MesaSkyEnvironment? mesaSky; private ConfigEntry<float> mesaSkyHour; private static string ChestMagic => "Toozy.KOTH.Chest/1/" + Suite.Epoch; internal bool ChestActionsActive => RoundActionsActive; private bool OwnsArenaEnding { get { if (session != null && !orphaned && InCustomLevel && HostAvailable) { return session.phase < SessionPhase.Returning; } return false; } } private static string PushWireMagic => "Toozy.KOTH.Push/1/" + Suite.Epoch; private bool PushSessionActive { get { if (initialized && !transitioning && !orphaned && InCustomLevel && PhotonNetwork.InRoom) { SessionPacket? sessionPacket = session; if (sessionPacket != null && sessionPacket.phase == SessionPhase.Playing) { return HostAvailable; } } return false; } } private bool RoundActionsActive { get { if (PushSessionActive) { HillScorePacket? hillScorePacket = hillScores; if (hillScorePacket != null && hillScorePacket.roundEnd == RoundEnd.None) { return hillScores.countdownRemaining == 0.0; } } return false; } } private static string HillWireMagic => "Toozy.KOTH.Score/1/" + Suite.Epoch; private bool ReplayViewActive { get { Func<bool>? active = replay.Active; if (active == null || !active()) { return replayArena; } return true; } } private static string ReplayWire => WireMagic + "/Replay/1/1.2.0"; private static string WireMagic => "Toozy.KOTH/1/" + Suite.Epoch; private bool HostAvailable { get { if (SuiteEnabled && PhotonNetwork.InRoom && PhotonNetwork.MasterClient != null) { return Property(PhotonNetwork.MasterClient, "koth.host") == "1.2.0"; } return false; } } private bool AwaitingArenaStart { get { if (initialized && !orphaned && InCustomLevel && HostAvailable) { SessionPacket? sessionPacket = session; if (sessionPacket == null) { return false; } return sessionPacket.phase == SessionPhase.Spawn; } return false; } } private bool RoundInputLocked { get { if (PushSessionActive || AwaitingArenaStart) { return RoundReadiness.LockInput(AwaitingArenaStart, hillScores != null, hillScores?.countdownRemaining ?? 0.0); } return false; } } private static bool InCustomLevel { get { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (SuiteEnabled) { Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == "Level_KOTH"; } return false; } } private static bool SuiteEnabled { get { if (Suite.Active("koth")) { return !Suite.ReplayActive; } return false; } } private static bool SuiteMenuManaged => true; private static bool SuiteMenuVisible => Suite.MenuOpen; private static bool MissingArenaAchievementStats(AchievementManager manager) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!SuiteEnabled) { Plugin? plugin = survivalOwner; if (plugin == null || !plugin.ReplayViewActive) { goto IL_0043; } } if (!((Object)(object)survivalOwner == (Object)null)) { Scene activeScene = SceneManager.GetActiveScene(); if (!(((Scene)(ref activeScene)).name != "Level_KOTH")) { SerializableRunBasedValues runBasedValueData = manager.runBasedValueData; if (RunFloatCounters.Invoke(ref runBasedValueData) != null) { return RunIntCounters.Invoke(ref runBasedValueData) == null; } return true; } } goto IL_0043; IL_0043: return false; } private void CaptureChestAnimation() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if ((Object)(object)chestAnimation != (Object)null) { return; } GameObject obj = Resources.Load<GameObject>("0_Items/LuggageSmall"); object obj2; if (obj == null) { obj2 = null; } else { Animator component = obj.GetComponent<Animator>(); obj2 = ((component != null) ? component.runtimeAnimatorController : null); } RuntimeAnimatorController val = (RuntimeAnimatorController)obj2; if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Native luggage animation controller is unavailable."); return; } chestAnimation = new AnimatorOverrideController(val); List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); chestAnimation.GetOverrides(list); for (int i = 0; i < list.Count; i++) { AnimationClip val2 = Object.Instantiate<AnimationClip>(list[i].Key); val2.events = Array.Empty<AnimationEvent>(); chestClips.Add(val2); list[i] = new KeyValuePair<AnimationClip, AnimationClip>(list[i].Key, val2); } chestAnimation.ApplyOverrides((IList<KeyValuePair<AnimationClip, AnimationClip>>)list); } private void DisposeChestAnimation() { if ((Object)(object)chestAnimation != (Object)null) { Object.Destroy((Object)(object)chestAnimation); } chestAnimation = null; foreach (AnimationClip chestClip in chestClips) { if ((Object)(object)chestClip != (Object)null) { Object.Destroy((Object)(object)chestClip); } } chestClips.Clear(); } private void BindArenaChests(Scene scene) { ResetArenaChests(); Transform[] array = (from t in ((Scene)(ref scene)).GetRootGameObjects().SelectMany((GameObject g) => g.GetComponentsInChildren<Transform>(true)) where ((Component)t).gameObject.activeInHierarchy && ((Object)t).name.StartsWith("__KOTH_Chest_v1:", StringComparison.Ordinal) select t).OrderBy<Transform, string>(Hierarchy, StringComparer.Ordinal).ToArray(); if (array.Length > 64) { throw new InvalidOperationException("Too many arena chests."); } if (array.Length != 0 && (Object)(object)chestAnimation == (Object)null) { throw new InvalidOperationException("Native luggage animation was not captured in the airport."); } Transform[] array2 = array; int num = 0; while (num < array2.Length) { Transform obj = array2[num]; KothChestDefinition kothChestDefinition = JsonConvert.DeserializeObject<KothChestDefinition>(((Object)obj).name.Substring("__KOTH_Chest_v1:".Length)); if (kothChestDefinition == null || !kothChestDefinition.Valid()) { throw new InvalidOperationException("Invalid exported chest settings."); } Transform parent = obj.parent; if (!((Object)(object)parent == (Object)null) && !((Object)(object)parent.Find("Visual/LuggageSmall/luggage/Lid") == (Object)null)) { Transform obj2 = parent.Find("LootPoints"); if (obj2 != null && obj2.childCount == 4) { ArenaChest arenaChest = ((Component)parent).gameObject.AddComponent<ArenaChest>(); arenaChest.Initialize(this, arenaChests.Count, kothChestDefinition, (RuntimeAnimatorController)(object)chestAnimation); arenaChests.Add(arenaChest); num++; continue; } } throw new InvalidOperationException("Exported chest hierarchy is incomplete."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Rechargeable chests bound: " + arenaChests.Count + "; native E interaction and luggage animation.")); static string Hierarchy(Transform t) { if (!((Object)(object)t.parent == (Object)null)) { return Hierarchy(t.parent) + "/" + t.GetSiblingIndex().ToString("D5"); } return t.GetSiblingIndex().ToString("D5"); } } private void ResetArenaChests() { foreach (ArenaChest arenaChest in arenaChests) { if ((Object)(object)arenaChest != (Object)null) { arenaChest.StopInteraction(); Object.Destroy((Object)(object)arenaChest); } } arenaChests.Clear(); chestInputSequence = (chestStateSequence = 0L); } internal void SendChestIntent(int chest, ChestInputKind kind) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (ChestActionsActive && session != null) { ChestIntent chestIntent = new ChestIntent { token = session.token, chest = chest, kind = kind, sequence = ++chestInputSequence }; object[] obj = new object[2] { ChestMagic, JsonConvert.SerializeObject((object)chestIntent) }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { session.host }; PhotonNetwork.RaiseEvent((byte)192, (object)obj, val, SendOptions.SendReliable); } } private void ReceiveChestEvent(EventData ev) { if (!PushSessionActive || session == null || !(ev.CustomData is object[] array) || array.Length != 2 || !(array[0] is string text) || text != ChestMagic || !(array[1] is string { Length: <=16384 } text2)) { return; } try { if (ev.Code != 192) { ChestSnapshot chestSnapshot = JsonConvert.DeserializeObject<ChestSnapshot>(text2); if (chestSnapshot != null && chestSnapshot.Valid(session, ev.Sender, PhotonNetwork.MasterClient.ActorNumber, chestStateSequence, arenaChests.Count)) { ApplyChestSnapshot(chestSnapshot); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected chest message: " + ex.Message)); } } private void ApplyChestSnapshot(ChestSnapshot packet) { chestStateSequence = packet.sequence; ChestRow[] rows = packet.rows; foreach (ChestRow chestRow in rows) { arenaChests[chestRow.id].Apply(chestRow); } } private void CancelPendingAttachment(CharacterItems items) { if (pendingItemAttachments.TryGetValue(items, out PendingItemAttachment value)) { pendingItemAttachments.Remove(items); if (value.routine != null) { ((MonoBehaviour)this).StopCoroutine(value.routine); } value.RestoreColliders(); } } private void CancelAllAttachments() { foreach (CharacterItems item in new List<CharacterItems>(pendingItemAttachments.Keys)) { CancelPendingAttachment(item); } } private static void DetachArenaHands(Character c) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) BodypartType[] array = (BodypartType[])(object)new BodypartType[2] { (BodypartType)7, (BodypartType)10 }; foreach (BodypartType key in array) { Bodypart value; Rigidbody val = (c.refs.ragdoll.partDict.TryGetValue(key, out value) ? value.Rig : null); if (!((Object)(object)val == (Object)null)) { FixedJoint[] components = ((Component)val).GetComponents<FixedJoint>(); for (int j = 0; j < components.Length; j++) { Object.Destroy((Object)(object)components[j]); } } } } private void EquipArenaItem(CharacterItems items, Character c, Item item) { CancelPendingAttachment(items); PressedDrop?.SetValue(items, false); items.UnAttachEquippedItem(); if ((Object)(object)item == (Object)null) { return; } c.data.currentItem = item; item.holderCharacter = c; NativeItemState(item, (ItemState)1, c); pushAnimations.Remove(((MonoBehaviourPun)c).photonView.ViewID); PendingItemAttachment pendingItemAttachment = new PendingItemAttachment { item = item, colliders = item.colliders }; pendingItemAttachment.enabled = new bool[pendingItemAttachment.colliders.Length]; for (int i = 0; i < pendingItemAttachment.colliders.Length; i++) { if ((Object)(object)pendingItemAttachment.colliders[i] != (Object)null) { pendingItemAttachment.enabled[i] = pendingItemAttachment.colliders[i].enabled; pendingItemAttachment.colliders[i].enabled = false; } } pendingItemAttachments[items] = pendingItemAttachment; pendingItemAttachment.routine = ((MonoBehaviour)this).StartCoroutine(AttachArenaItem(items, c, item, pendingItemAttachment)); } private IEnumerator AttachArenaItem(CharacterItems items, Character c, Item item, PendingItemAttachment pending) { try { int frame = 0; while (true) { if (frame < 3) { yield return (object)new WaitForFixedUpdate(); if (Current()) { c.data.sinceItemAttach = 0f; NativeMoveItem(item, items.GetItemHoldPos(item, true), NativeHoldRotation(items, item)); if (!item.rig.isKinematic) { item.rig.linearVelocity = Vector3.zero; item.rig.angularVelocity = Vector3.zero; } frame++; continue; } break; } if (Current()) { NativeAttachItem(items, item); } break; } } finally { Plugin plugin = this; if (plugin.pendingItemAttachments.TryGetValue(items, out PendingItemAttachment value) && value == pending) { plugin.pendingItemAttachments.Remove(items); pending.RestoreColliders(); } bool Current() { if ((Object)(object)c != (Object)null && (Object)(object)items != (Object)null && (Object)(object)item != (Object)null && (Object)(object)c.data.currentItem == (Object)(object)item && !c.data.dead && ArenaSurvivalApplies(c) && pendingItemAttachments.TryGetValue(items, out PendingItemAttachment value2)) { return value2 == pending; } return false; } } } private void ConfigureLighting() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown arenaSunIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "ArenaSunIntensity", 1.6f, new ConfigDescription("Directional daylight brightness in the KOTH arena.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.5f), Array.Empty<object>())); arenaShadowFill = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "ArenaShadowFill", 0.35f, new ConfigDescription("Minimum native ambient light in arena shadows (0-1). Higher is brighter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.65f), Array.Empty<object>())); } private Transform? ChooseArenaSpawn(Character character) { if (arenaSpawnPoints.Length == 0) { return null; } int ownerActorNr = ((MonoBehaviourPun)character).photonView.OwnerActorNr; int[] array = (from i in Enumerable.Range(0, arenaSpawnPoints.Length) where (Object)(object)arenaSpawnPoints[i] != (Object)null select i).ToArray(); if (lastArenaSpawn.TryGetValue(ownerActorNr, out var previous) && array.Length > 1) { array = array.Where((int i) => i != previous).ToArray(); } int[] array2 = array.Where((int i) => !Character.AllCharacters.Any(delegate(Character c) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c != (Object)null && (Object)(object)c != (Object)(object)character && !c.data.dead) { Scene scene = ((Component)c).gameObject.scene; if (((Scene)(ref scene)).name == "Level_KOTH") { Vector3 val = c.Center - arenaSpawnPoints[i].position; return ((Vector3)(ref val)).sqrMagnitude < 9f; } } return false; })).ToArray(); if (array2.Length != 0) { array = array2; } if (array.Length == 0) { return null; } int num = array[Random.Range(0, array.Length)]; lastArenaSpawn[ownerActorNr] = num; return arenaSpawnPoints[num]; } private bool InstallSurvivalRules() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown survivalOwner = this; survivalHarmony = new Harmony("toozy.peak.koth.survival"); try { Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.Namespace == typeof(Plugin).Namespace && type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { survivalHarmony.CreateClassProcessor(type).Patch(); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Arena survival rules ready: no hunger; no landing or climbing-impact injury. Knockback and other injury sources retained."); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Required arena survival hooks failed; loader disabled: " + ex)); RemoveSurvivalRules(); return false; } } private void RemoveSurvivalRules() { Harmony? obj = survivalHarmony; if (obj != null) { obj.UnpatchSelf(); } survivalHarmony = null; if (survivalOwner == this) { survivalOwner = null; } fallDamageCharacter = null; } private static bool ArenaSurvivalApplies(Character character) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Plugin plugin = survivalOwner; if (SuiteEnabled && (Object)(object)plugin != (Object)null && (Object)(object)character != (Object)null && (Object)(object)((MonoBehaviourPun)character).photonView != (Object)null) { SessionPacket? sessionPacket = plugin.session; bool num = plugin.orphaned; Scene val = SceneManager.GetActiveScene(); string name = ((Scene)(ref val)).name; val = ((Component)character).gameObject.scene; return ArenaSurvivalPolicy.Applies(sessionPacket, num, name, ((Scene)(ref val)).name, ((MonoBehaviourPun)character).photonView.OwnerActorNr); } return false; } private void BeginShove(Character c, Vector3 velocity) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) float num = (((Object)(object)shovedCharacter == (Object)(object)c) ? shoveBaseline : Mathf.Max(0f, Vector3.Dot(c.data.avarageVelocity, ((Vector3)(ref velocity)).normalized))); EndShove(); shovedCharacter = c; shoveOrigin = c.Center; shoveDirection = ((Vector3)(ref velocity)).normalized; shovePeak = Mathf.Min(PushRules.Speed(1f), ((Vector3)(ref velocity)).magnitude); shoveLimit = Mathf.Min(2f, shovePeak * 0.5f / 2f); shoveBaseline = num; shoveElapsed = 0f; } private void FixedUpdate() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Character val = shovedCharacter; if ((Object)(object)val == (Object)null) { return; } if (!PushSessionActive || val.warping || val.data.dead || val.data.fullyPassedOut || !((MonoBehaviourPun)val).photonView.IsMine) { EndShove(); return; } float num = shoveLimit - Mathf.Max(0f, Vector3.Dot(val.Center - shoveOrigin, shoveDirection)); if (num <= 0f || shoveElapsed >= 0.5f) { EndShove(); return; } float speed = Mathf.Min(shovePeak * PushRules.Envelope(shoveElapsed + Time.fixedDeltaTime / 2f), num / Time.fixedDeltaTime); MaintainShoveSpeed(speed); shoveElapsed += Time.fixedDeltaTime; } private void MaintainShoveSpeed(float speed) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shovedCharacter == (Object)null) { return; } foreach (Rigidbody item in (from p in shovedCharacter.refs.ragdoll.partList where (Object)(object)p != (Object)null select p.Rig into r where (Object)(object)r != (Object)null && !r.isKinematic select r).Distinct()) { float num = PushRules.VelocityCorrection(Vector3.Dot(item.linearVelocity, shoveDirection), shoveBaseline, speed, shovePeak); item.AddForce(shoveDirection * num, (ForceMode)2); } } private void EndShove() { if ((Object)(object)shovedCharacter != (Object)null && !shovedCharacter.warping) { MaintainShoveSpeed(0f); } shovedCharacter = null; } private void ConfigurePush() { pushKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Push", "Key", (KeyCode)102, "Hold to charge, release to shove in the arena. Right-click kick remains separate."); } private static Character? ArenaCharacter(int actor) { return ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)delegate(Character c) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c != (Object)null) { Scene scene = ((Component)c).gameObject.scene; if (((Scene)(ref scene)).name == "Level_KOTH" && (Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.OwnerActorNr == actor) { return c.IsRegisteredToPlayer; } } return false; }); } private static bool CanPush(Character? c) { if ((Object)(object)c != (Object)null && ((Component)c).gameObject.activeInHierarchy && !c.warping && !c.data.dead && !c.data.passedOut && !c.data.fullyPassedOut && !Object.op_Implicit((Object)(object)c.data.carrier) && (Object)(object)c.data.carriedPlayer == (Object)null && !c.data.isClimbingAnything && !Object.op_Implicit((Object)(object)c.data.currentClimbHandle) && !c.data.isKicking && c.data.currentStamina + c.data.extraStamina > 0f && c.data.currentRagdollControll > 0.5f) { return c.data.fallSeconds <= 0f; } return false; } private void UpdateChargedPush() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_0134: Unknown result type (might be due to invalid IL or missing references) double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; Character localCharacter = Character.localCharacter; if (!RoundActionsActive || !CanPush(localCharacter) || !localCharacter.IsLocal || !((MonoBehaviourPun)localCharacter).photonView.IsMine || !Application.isFocused || MenuWindow.AllActiveWindows.Count != 0 || (int)Cursor.lockState != 1) { CancelLocalPush(); return; } if (Input.GetKeyDown(pushKey.Value) && !pushCharging && realtimeSinceStartupAsDouble >= localPushReady) { pushCharging = true; pushStarted = realtimeSinceStartupAsDouble; nextPushHeartbeat = realtimeSinceStartupAsDouble + 0.4; localChargeId = pushInputSequence + 1; SendPushIntent(PushInputKind.Begin); } if (pushCharging) { if (!UsePushStamina(localCharacter, 0.15f * Time.deltaTime)) { CancelLocalPush(); PushNotice("Out of stamina — push cancelled"); } else if (Input.GetKeyUp(pushKey.Value)) { pushCharging = false; releasedChargeId = localChargeId; StartPushAnimation(localCharacter); localPushReady = realtimeSinceStartupAsDouble + 1.2; PushNotice("Shoving..."); SendPushIntent(PushInputKind.Release); } else if (!Input.GetKey(pushKey.Value)) { CancelLocalPush(); } else if (realtimeSinceStartupAsDouble >= nextPushHeartbeat) { nextPushHeartbeat = realtimeSinceStartupAsDouble + 0.4; SendPushIntent(PushInputKind.Hold); } } } private void SendPushIntent(PushInputKind kind) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (session != null && PhotonNetwork.InRoom && PushSessionActive) { PushIntent pushIntent = new PushIntent { token = session.token, round = (hillScores?.round ?? 1), sequence = ++pushInputSequence, chargeId = localChargeId, kind = kind }; object[] obj = new object[2] { PushWireMagic, JsonConvert.SerializeObject((object)pushIntent) }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { session.host }; PhotonNetwork.RaiseEvent((byte)190, (object)obj, val, SendOptions.SendReliable); } } private void CancelLocalPush() { if (pushCharging) { SendPushIntent(PushInputKind.Cancel); pushCharging = false; } } private void ResetPushState() { EndShove(); pushAnimations.Clear(); DestroyPushMeter(); pushCharging = false; pushInputSequence = (localChargeId = (releasedChargeId = (lastPushResultSequence = 0L))); localPushReady = (pushNoticeUntil = 0.0); pushNotice = ""; } private void ReceivePushEvent(EventData ev) { if (!PushSessionActive || session == null || !(ev.CustomData is object[] array) || array.Length != 2 || !(array[0] is string text) || text != PushWireMagic || !(array[1] is string { Length: <=2048 } text2)) { return; } try { if (ev.Code != 190 && RoundActionsActive && ev.Sender == session.host && ev.Sender == PhotonNetwork.MasterClient.ActorNumber) { PushResult pushResult = JsonConvert.DeserializeObject<PushResult>(text2); if (pushResult != null && pushResult.round == hillScores?.round && pushResult.Valid(session, ev.Sender, PhotonNetwork.MasterClient.ActorNumber, lastPushResultSequence)) { ApplyPushResult(pushResult); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected KOTH push message: " + ex.Message)); } } private void ApplyPushResult(PushResult result) { //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) lastPushResultSequence = result.sequence; int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (result.outcome != PushOutcome.Cancelled && result.attacker != actorNumber) { Character val = ArenaCharacter(result.attacker); if ((Object)(object)val != (Object)null) { StartPushAnimation(val); } } if (result.attacker == actorNumber && result.chargeId == releasedChargeId) { localPushReady = Time.realtimeSinceStartupAsDouble + 1.2; Player player = PhotonNetwork.CurrentRoom.GetPlayer(result.target, false); string text = ((player == null) ? "player" : new string(player.NickName.Where((char ch) => !char.IsControl(ch)).Take(22).ToArray())); PushNotice((result.outcome == PushOutcome.Hit) ? ("Pushed " + text + "!") : ((result.outcome == PushOutcome.Miss) ? "Missed — get closer and aim at a player" : "Push cancelled")); } if (result.outcome != PushOutcome.Hit || result.target != actorNumber) { return; } Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && localCharacter.IsLocal && ((MonoBehaviourPun)localCharacter).photonView.IsMine && ((MonoBehaviourPun)localCharacter).photonView.ViewID == result.targetView) { Scene scene = ((Component)localCharacter).gameObject.scene; if (!(((Scene)(ref scene)).name != "Level_KOTH") && !localCharacter.warping && !localCharacter.data.dead && !localCharacter.data.fullyPassedOut) { CancelLocalPush(); localCharacter.refs.climbing.StopAnyClimbing(); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(result.velocity[0], result.velocity[1], result.velocity[2]); BeginShove(localCharacter, val2); PushNotice("You were pushed!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"PUSH applied: attacker={result.attacker}; charge={result.charge:F2}; velocity={val2}."); } } } private void PushNotice(string text) { pushNotice = text; pushNoticeUntil = Time.realtimeSinceStartupAsDouble + 1.6; } private void DrawPushHud() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) if (PushSessionActive) { double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; float num = (pushCharging ? PushRules.Charge(realtimeSinceStartupAsDouble - pushStarted) : 0f); string text = (pushCharging ? (((num >= 1f) ? "FULL POWER — release " : "CHARGING — release ") + ((object)pushKey.Value/*cast due to .constrained prefix*/).ToString() + " to push") : ((realtimeSinceStartupAsDouble < pushNoticeUntil) ? pushNotice : ((realtimeSinceStartupAsDouble < localPushReady) ? ("Push ready in " + (localPushReady - realtimeSinceStartupAsDouble).ToString("0.0") + "s") : ("Hold " + ((object)pushKey.Value/*cast due to .constrained prefix*/).ToString() + " to charge a push")))); float num2 = Mathf.Min(400, Screen.width - 40); float num3 = ((float)Screen.width - num2) / 2f; float num4 = (float)Screen.height * 0.72f; GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 16, richText = false }; GUI.Box(new Rect(num3, num4, num2, (float)(pushCharging ? 58 : 36)), ""); GUI.Label(new Rect(num3 + 8f, num4 + 4f, num2 - 16f, 27f), text, val); if (pushCharging) { Color color = GUI.color; GUI.color = new Color(0.15f, 0.15f, 0.15f, 1f); GUI.DrawTexture(new Rect(num3 + 12f, num4 + 37f, num2 - 24f, 10f), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.Lerp(new Color(0.35f, 0.78f, 0f), new Color(0.75f, 0.93f, 0.11f), num); GUI.DrawTexture(new Rect(num3 + 12f, num4 + 37f, (num2 - 24f) * num, 10f), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } } } private void CaptureCustomizationCatalog(GameObject inactiveCache) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Customization instance = Singleton<Customization>.Instance; ValidateCustomizationCatalog(instance); GameObject val = new GameObject("KOTH_Customization"); val.transform.SetParent(inactiveCache.transform, false); Customization obj = val.AddComponent<Customization>(); obj.skins = instance.skins; obj.accessories = instance.accessories; obj.eyes = instance.eyes; obj.mouths = instance.mouths; obj.fits = instance.fits; obj.hats = instance.hats; obj.sashes = instance.sashes; obj.medals = instance.medals; obj.goatHat = instance.goatHat; obj.crownHat = instance.crownHat; obj.ascendantMedal = instance.ascendantMedal; } private void ActivateCustomizationCatalog(GameObject systems) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) Transform val = systems.transform.Find("KOTH_Customization"); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Customization catalogue was not prepared."); } val.SetParent((Transform)null, true); Customization instance = Singleton<Customization>.Instance; if ((Object)(object)instance != (Object)(object)((Component)val).GetComponent<Customization>()) { throw new InvalidOperationException("Custom-level customization catalogue did not become active."); } ValidateCustomizationCatalog(instance); ManualLogSource logger = ((BaseUnityPlugin)this).Logger; object[] array = new object[4]; Scene scene = ((Component)instance).gameObject.scene; array[0] = ((Scene)(ref scene)).name; array[1] = instance.skins.Length; array[2] = instance.fits.Length; array[3] = instance.hats.Length; logger.LogInfo((object)string.Format("Customization catalogue ready in {0}: skins={1}; outfits={2}; hats={3}.", array)); } private static void ValidateCustomizationCatalog(Customization catalog) { if ((Object)(object)catalog == (Object)null || catalog.skins == null || catalog.skins.Length == 0 || catalog.accessories == null || catalog.accessories.Length == 0 || catalog.eyes == null || catalog.eyes.Length == 0 || catalog.mouths == null || catalog.mouths.Length == 0 || catalog.fits == null || catalog.fits.Length == 0 || catalog.hats == null || catalog.hats.Length == 0 || catalog.sashes == null || catalog.sashes.Length == 0 || catalog.medals == null || catalog.medals.Length == 0) { throw new InvalidOperationException("PEAK's customization catalogue is missing or incomplete."); } } private void BindHillZone(Scene scene) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) Transform[] array = (from t in ((Scene)(ref scene)).GetRootGameObjects().SelectMany((GameObject g) => g.GetComponentsInChildren<Transform>(true)) where ((Object)t).name == "__KOTH_HillZone_v1" && ((Component)t).gameObject.activeInHierarchy select t).ToArray(); if (array.Length > 1) { throw new InvalidOperationException("Map has more than one active Hill Zone."); } Transform? obj = array.SingleOrDefault(); hillZone = ((obj != null) ? ((Component)obj).GetComponent<BoxCollider>() : null); if (array.Length == 1 && ((Object)(object)hillZone == (Object)null || !KothHillGeometry.Valid(hillZone.size) || !((Collider)hillZone).isTrigger || ((Collider)hillZone).enabled)) { throw new InvalidOperationException("Invalid exported Hill Zone."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)(((Object)(object)hillZone != (Object)null) ? $"HILL zone ready: centre={((Component)hillZone).transform.TransformPoint(hillZone.center)}; size={hillZone.size}; scale={((Component)hillZone).transform.lossyScale}." : "HILL zone missing: arena exploration works, scoring is disabled.")); } private void ResetHillScores() { ResetArenaChests(); hillZone = null; hillScores = null; lastHillReceived = 0.0; } private void ReceiveHillScores(EventData ev) { if (session == null || orphaned || !PhotonNetwork.InRoom || !HostAvailable || ev.Sender != PhotonNetwork.MasterClient.ActorNumber || !(ev.CustomData is object[] array) || array.Length != 2 || !(array[0] is string text) || text != HillWireMagic || !(array[1] is string { Length: <=16384 } text2)) { return; } try { HillScorePacket hillScorePacket = JsonConvert.DeserializeObject<HillScorePacket>(text2); if (hillScorePacket != null && hillScorePacket.IsValid(session, ev.Sender, PhotonNetwork.MasterClient.ActorNumber, hillScores?.sequence ?? 0)) { AcceptHillScores(hillScorePacket); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected KOTH score packet: " + ex.Message)); } } private void AcceptHillScores(HillScorePacket packet) { if (hillScores != null && (hillScores.round != packet.round || packet.roundEnd != RoundEnd.None)) { CancelLocalPush(); EndShove(); pushAnimations.Clear(); } hillScores = packet; lastHillReceived = Time.realtimeSinceStartupAsDouble; } private string ReplayPlayerName(int actor) { return replayFrame?.State.people.FirstOrDefault((KothReplayPerson p) => p.actor == actor)?.name ?? ("Player " + actor); } private void ReplayUpdate() { //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) try { replay.Discover(); if (replay.Connected && !replayRegistered) { replay.Register?.Invoke("Level_KOTH", ValidateKothReplay, LoadKothReplay); replayRegistered = true; } bool replayViewActive = ReplayViewActive; if (replayViewActive && !replayWasActive) { SetSettingsOpen(open: false); CancelLocalPush(); EndShove(); pushAnimations.Clear(); teamFlags?.Dispose(); teamFlags = null; } if (!replayViewActive && replayWasActive) { RestoreReplayChests(); replayFrame = null; replayTimeline = null; replayLoadPath = null; replayLoad = null; } replayWasActive = replayViewActive; if (!replayViewActive && PushSessionActive && !LoadingScreenHandler.loading) { replay.ResumeAfterScene?.Invoke("Level_KOTH"); } TickReplayTelemetry(); string path = ""; double seconds = 0.0; bool flag = replay.Recording?.Invoke(out path, out seconds) ?? false; if (!flag || path != replayRecordPath) { CloseKothReplay(); if (flag && path != replayClosedPath && SuiteEnabled) { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "Level_KOTH" && session != null) { OpenKothReplay(path, seconds); } } } ReplayJournal? replayJournal = replayWriter; if (((replayJournal != null) ? replayJournal.Error : null) != null) { throw new IOException("KOTH sidecar write failed", replayWriter.Error); } ReplayJournal? replayJournal2 = lastReplayWriter; if (((replayJournal2 != null) ? replayJournal2.Error : null) != null) { Exception error = lastReplayWriter.Error; lastReplayWriter = null; ((BaseUnityPlugin)this).Logger.LogError((object)("Previous KOTH sidecar finalization failed: " + error)); replay.Warning?.Invoke("Previous KOTH presentation file could not finalize: " + error.Message); } Task? task = replayArchive; if (task != null && task.IsFaulted) { Exception baseException = replayArchive.Exception.GetBaseException(); replayArchive = null; ((BaseUnityPlugin)this).Logger.LogError((object)("Arena archive failed: " + baseException)); replay.Warning?.Invoke("KOTH map archive failed; retain the installed map bundle: " + baseException.Message); } } catch (Exception ex) { FailKothReplay(ex); } } private void OpenKothReplay(string path, double seconds) { replayRecordPath = path; replayClosedPath = path; replayPeople.Clear(); CaptureReplayPeople(); BindReplayCaptureChests(); replayHeader = new KothReplayHeader { version = "1.2.0", mapHash = mapHash, recorder = PhotonNetwork.LocalPlayer.ActorNumber, people = replayPeople.Values.ToArray(), chests = captureChests.Select((ReplayChestBinding c) => c.Paths).ToArray() }; if (!KothReplayTimeline.HeaderValid(replayHeader)) { throw new InvalidDataException("Arena replay metadata is incomplete."); } replayWriter = new ReplayJournal(path + ".minigames.jsonl"); WriteKothReplay(new KothReplayEvent { time = seconds, stream = "header", header = replayHeader }); replayStateSignature = ""; nextReplayState = (nextReplaySample = 0.0); replayNonce = Guid.NewGuid().ToString("N"); nextReplayRequest = 0.0; remoteReplayViews.Clear(); string bundle = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "koth_level.bundle"); string hash = mapHash; string key = ArchivedBundle(path, hash); if (!replayArchives.TryGetValue(key, out replayArchive) || replayArchive.IsFaulted) { replayArchives[key] = (replayArchive = Task.Run(delegate { ArchiveKothBundle(bundle, path, hash); })); } replay.Status?.Invoke("KOTH capture active: match HUD, chests, lighting and player UI."); } private void CaptureReplayPeople() { Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { replayPeople[val.ActorNumber] = new KothReplayPerson { actor = val.ActorNumber, identity = (val.UserId ?? ""), name = (val.NickName ?? "") }; } } private void CaptureKothReplay() { if (replayWriter == null || ReplayViewActive || replay.Recording == null || !replay.Recording(out var path, out var seconds) || path != replayRecordPath) { return; } try { double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; if (realtimeSinceStartupAsDouble >= nextReplayState && session != null) { nextReplayState = realtimeSinceStartupAsDouble + 0.1; CaptureReplayPeople(); KothReplayState kothReplayState = new KothReplayState { session = session, score = ((session.phase == SessionPhase.Playing && hillScores?.token == session.token) ? hillScores : null), active = PushSessionActive, sky = mesaSkyHour.Value, sun = arenaSunIntensity.Value, fill = arenaShadowFill.Value, people = replayPeople.Values.OrderBy((KothReplayPerson p) => p.actor).ToArray() }; string text = JsonConvert.SerializeObject((object)kothReplayState, ReplayJournal.Json); if (text != replayStateSignature) { replayStateSignature = text; kothReplayState.scoreAge = Math.Max(0.0, realtimeSinceStartupAsDouble - lastHillReceived); WriteKothReplay(new KothReplayEvent { time = seconds, stream = "state", state = kothReplayState }); } } if (realtimeSinceStartupAsDouble < nextReplaySample) { return; } nextReplaySample = realtimeSinceStartupAsDouble + 0.05; CaptureKothChests(seconds); CapturePrivateView(LocalReplayView(), seconds); foreach (RemoteReplayView value in remoteReplayViews.Values) { if (realtimeSinceStartupAsDouble - value.Received <= 0.75) { CapturePrivateView(value.View, seconds); } } } catch (Exception ex) { FailKothReplay(ex); } } private void WriteKothReplay(KothReplayEvent value) { ReplayJournal? replayJournal = replayWriter; if (replayJournal == null || !replayJournal.Write(value)) { throw new IOException("KOTH replay queue is full or its writer failed."); } } private void CloseKothReplay() { if (replayWriter != null) { replayWriter.Dispose(); lastReplayWriter = replayWriter; } replayWriter = null; replayRecordPath = null; replayNonce = ""; captureChests.Clear(); capturedViews.Clear(); capturedViewStates.Clear(); } private void FailKothReplay(Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("KOTH replay integration: " + ex)); replay.Warning?.Invoke("KOTH presentation capture incomplete: " + ex.Message); replay.Status?.Invoke("KOTH replay error: " + ex.Message); CloseKothReplay(); } private bool ReplayLateUpdate() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if (!ReplayViewActive) { return false; } replayFrame = null; if ((Object)(object)arenaUi != (Object)null) { arenaUi.SetActive(false); } if ((Object)(object)pushMeterCanvas != (Object)null) { pushMeterCanvas.SetActive(false); } if ((Object)(object)roundBlurVolume != (Object)null) { ((Behaviour)roundBlurVolume).enabled = false; } if (replay.Playback == null || !replay.Playback(out var path, out var seconds)) { return true; } try { if (path != replayLoadPath) { RestoreReplayChests(); replayLoadPath = path; replayTimeline = null; Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Level_KOTH") { replayLoad = null; return true; } Task previous = lastReplayWriter?.Completion; replayLoad = Task.Run(async delegate { if (previous != null) { await previous; } return KothReplayTimeline.Load(path + ".minigames.jsonl"); }); } Task<KothReplayTimeline>? task = replayLoad; if (task != null && task.IsCompleted) { Task<KothReplayTimeline> task2 = replayLoad; replayLoad = null; if (task2.IsFaulted) { throw task2.Exception.GetBaseException(); } replayTimeline = task2.Result; BindReplayPlaybackChests(replayTimeline.Header); replay.Status?.Invoke("KOTH replay loaded. HUD/effects follow the selected recorded scout."); } if (replayTimeline == null) { return true; } KothReplayEvent next; KothReplayEvent kothReplayEvent = replayTimeline.At("state", seconds, out next); KothReplayState kothReplayState = kothReplayEvent?.state; if (kothReplayState == null) { return true; } ApplyKothReplayChests(seconds); mesaSky?.Apply(kothReplayState.sky); arenaLighting?.Apply(kothReplayState.sun, kothReplayState.fill); KothReplayFrame kothReplayFrame = new KothReplayFrame { State = kothReplayState, Time = seconds, ScoreAge = kothReplayState.scoreAge + seconds - kothReplayEvent.time }; ReplayConnection.Viewer? view = replay.View; if (view != null && view(out var _, out var _, out var track, out var identity, out var _, out var _, out var hud, out var effects, out var _, out var _, out var inventory)) { kothReplayFrame.Actor = replayTimeline.Resolve(kothReplayState, track, identity); kothReplayFrame.Hud = hud && kothReplayFrame.Actor > 0; kothReplayFrame.Effects = effects && kothReplayFrame.Actor > 0; kothReplayFrame.Inventory = inventory; KothReplayEvent next2; KothReplayEvent kothReplayEvent2 = replayTimeline.At("view/" + kothReplayFrame.Actor, seconds, out next2); if (kothReplayEvent2?.view != null && seconds - kothReplayEvent2.time <= 0.75) { KothReplayPrivate view2 = kothReplayEvent2.view; float num = KothReplayTimeline.Mix(kothReplayEvent2, next2, seconds); kothReplayFrame.Hud &= view2.hud; kothReplayFrame.Charging = view2.charging; kothReplayFrame.Charge = ((view2.charging && next2 != null && next2.view?.charging == true) ? Mathf.Lerp(view2.charge, next2.view.charge, num) : view2.charge); kothReplayFrame.Blur = ((next2?.view != null) ? Mathf.Lerp(view2.blur, next2.view.blur, num) : view2.blur); } } replayFrame = kothReplayFrame; if ((Object)(object)arenaUi != (Object)null) { arenaUi.SetActive(true); } UpdateArenaUi(); UpdatePushMeter(); } catch (Exception ex) { replayTimeline = null; replay.Status?.Invoke("KOTH replay unavailable: " + ex.Message); ((BaseUnityPlugin)this).Logger.LogWarning((object)("KOTH replay presentation: " + ex)); } return true; } private void DisposeKothReplay() { CloseKothReplay(); RestoreReplayChests(); if (replayRegistered) { replay.Unregister?.Invoke("Level_KOTH"); } PhotonNetwork.NetworkingClient.EventReceived -= ReceiveReplayTelemetry; } private static string ChestNodePath(Transform node, Transform root) { List<int> list = new List<int>(); Transform val = node; while ((Object)(object)val != (Object)(object)root) { if ((Object)(object)val == (Object)null) { throw new InvalidDataException("Chest node outside root."); } list.Add(val.GetSiblingIndex()); val = val.parent; } list.Reverse(); return string.Join("/", list); } private void BindReplayCaptureChests() { captureChests.Clear(); foreach (ArenaChest chest in arenaChests) { Transform[] componentsInChildren = ((Component)((Component)chest).transform.Find("Visual/LuggageSmall")).GetComponentsInChildren<Transform>(true); if (componentsInChildren.Length > 128) { throw new InvalidDataException("Chest hierarchy exceeds replay bounds."); } captureChests.Add(new ReplayChestBinding { Nodes = componentsInChildren, Paths = componentsInChildren.Select((Transform t) => ChestNodePath(t, ((Component)chest).transform)).ToArray(), Last = new float[componentsInChildren.Length * 10], Scratch = new float[componentsInChildren.Length * 10] }); } } private static void ReadChestPose(ReplayChestBinding b, float[] values) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < b.Nodes.Length; i++) { Transform obj = b.Nodes[i]; if ((Object)(object)obj == (Object)null) { throw new InvalidDataException("Chest disappeared during recording."); } int num = i * 10; Vector3 localPosition = obj.localPosition; Quaternion localRotation = obj.localRotation; Vector3 localScale = obj.localScale; values[num] = localPosition.x; values[num + 1] = localPosition.y; values[num + 2] = localPosition.z; values[num + 3] = localRotation.x; values[num + 4] = localRotation.y; values[num + 5] = localRotation.z; values[num + 6] = localRotation.w; values[num + 7] = localScale.x; values[num + 8] = localScale.y; values[num + 9] = localScale.z; } } private void CaptureKothChests(double seconds) { for (int i = 0; i < captureChests.Count; i++) { ReplayChestBinding replayChestBinding = captureChests[i]; ReadChestPose(replayChestBinding, replayChestBinding.Scratch); bool flag = replayChestBinding.LastWritten < 0.0; int num = 0; while (!flag && num < replayChestBinding.Last.Length) { flag = Math.Abs(replayChestBinding.Last[num] - replayChestBinding.Scratch[num]) > 1E-05f; num++; } if (flag) { if (replayChestBinding.LastWritten >= 0.0 && replayChestBinding.LastSample > replayChestBinding.LastWritten) { WriteKothReplay(new KothReplayEvent { time = replayChestBinding.LastSample, stream = "chest/" + i, pose = replayChestBinding.Last }); } WriteKothReplay(new KothReplayEvent { time = seconds, stream = "chest/" + i, pose = replayChestBinding.Scratch }); Array.Copy(replayChestBinding.Scratch, replayChestBinding.Last, replayChestBinding.Last.Length); replayChestBinding.LastWritten = seconds; } replayChestBinding.LastSample = seconds; } } private void BindReplayPlaybackChests(KothReplayHeader header) { RestoreReplayChests(); if (arenaChests.Count != header.chests.Length) { throw new InvalidDataException("Recorded arena chest count differs."); } for (int i = 0; i < header.chests.Length; i++) { ArenaChest chest = arenaChests[i]; Transform[] array = header.chests[i].Select(Find).ToArray(); ReplayChestBinding replayChestBinding = new ReplayChestBinding { Nodes = array, Last = new float[array.Length * 10], Animator = ((Component)chest).GetComponentInChildren<Animator>(true) }; ReadChestPose(replayChestBinding, replayChestBinding.Last); if ((Object)(object)replayChestBinding.Animator != (Object)null) { replayChestBinding.AnimatorEnabled = ((Behaviour)replayChestBinding.Animator).enabled; ((Behaviour)replayChestBinding.Animator).enabled = false; } chest.StopInteraction(); playbackChests.Add(replayChestBinding); Transform Find(string path) { Transform val = ((Component)chest).transform; string[] array2 = path.Split('/'); for (int j = 0; j < array2.Length; j++) { int num = int.Parse(array2[j]); if (num >= val.childCount) { throw new InvalidDataException("Recorded chest hierarchy differs."); } val = val.GetChild(num); } return val; } } } private static void ApplyChestPose(ReplayChestBinding binding, float[] a, float[] b, float mix) { //IL_002c: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < binding.Nodes.Length; i++) { Transform val = binding.Nodes[i]; int n; if (!((Object)(object)val == (Object)null)) { n = i * 10; val.localPosition = Vector3.LerpUnclamped(V(a, n), V(b, n), mix); val.localRotation = Quaternion.SlerpUnclamped(Q(a), Q(b), mix); val.localScale = Vector3.LerpUnclamped(V(a, n + 7), V(b, n + 7), mix); } Quaternion Q(float[] p) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) return new Quaternion(p[n + 3], p[n + 4], p[n + 5], p[n + 6]); } } stat