Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TokControl REPO Tiktoklive v1.3.91
BepInEx\plugins\TokControl_REPO_Tiktoklive.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.Net; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Modules; using TMPro; using TokControlREPOBridge.Commands; using TokControlREPOBridge.Logging; using TokControlREPOBridge.Network; using TokControlREPOBridge.Ui; using TokControlREPOBridge.Util; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TokControl_REPO_Tiktoklive")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("TokControl WebSocket bridge for R.E.P.O. TikTok Live — spawn items and enemies from stream gifts")] [assembly: AssemblyFileVersion("1.3.91.0")] [assembly: AssemblyInformationalVersion("1.3.91")] [assembly: AssemblyProduct("TokControl_REPO_Tiktoklive")] [assembly: AssemblyTitle("TokControl_REPO_Tiktoklive")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.91.0")] [module: UnverifiableCode] 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; } } internal static class IsExternalInit { } } namespace TokControlREPOBridge { [BepInPlugin("com.tokcontrol.repobridge", "TokControl_REPO_Tiktoklive", "1.3.91")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private ConfigEntry<int> _portConfig; private ConfigEntry<bool> _logToUnityConfig; private ConfigEntry<string> _defaultGhostEnemyConfig; private WebSocketServer? _server; private CommandProcessor? _processor; private Harmony? _harmony; private static readonly ConcurrentQueue<Action> MainThreadQueue = new ConcurrentQueue<Action>(); private static readonly List<(float due, Action action)> DelayedActions = new List<(float, Action)>(); private static readonly object DelayedLock = new object(); private const int MinActionsPerFrame = 16; private const int MaxBurstActionsPerFrame = 256; internal static Plugin Instance { get; private set; } = null; internal static ManualLogSource Log { get; private set; } = null; internal static void EnqueueMainThread(Action action) { if (action != null) { MainThreadQueue.Enqueue(action); } } internal static void EnqueueMainThreadDelayed(Action action, float delaySeconds) { if (action == null) { return; } if (delaySeconds <= 0.001f) { EnqueueMainThread(action); return; } lock (DelayedLock) { DelayedActions.Add((Time.realtimeSinceStartup + delaySeconds, action)); } } private void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); ModLog.Info("=== TokControl_REPO_Tiktoklive v1.3.91 ==="); ModLog.Info("REPOLib dependency OK — initializing WebSocket bridge"); try { _harmony = new Harmony("com.tokcontrol.repobridge"); _harmony.PatchAll(typeof(Plugin).Assembly); ModLog.Info("Enemy spawn patches applied"); } catch (Exception ex) { ModLog.Warn("Harmony patch failed: " + ex.Message); } _processor = new CommandProcessor(_defaultGhostEnemyConfig.Value); SpawnRelay.Initialize(_processor.Actions); EffectRelay.Initialize(_processor.Actions); SpeakBroadcast.Initialize(); try { _server = new WebSocketServer(_portConfig.Value, _processor); _server.Start(); ModLog.Info($"WebSocket listening on ws://127.0.0.1:{_server.Port}/"); if (_server.Port != _portConfig.Value) { ModLog.Warn($"Configured port {_portConfig.Value} was busy. Update TokControl URL → ws://127.0.0.1:{_server.Port}/"); } } catch (Exception ex2) { ModLog.Error("Failed to start WebSocket bridge: " + ex2.Message); ModLog.Error("Disable other TikTok/stream mods using port 8080, or change Server.Port in the config file."); _server = null; } MainThreadDispatcher.Enqueue(delegate { ItemRegistry.EnsureLoaded(); _ = EffectTimerHost.Instance; TokControlStatusHud.Ensure(); }); ModLog.Info("Waiting for TokControl / Pandy App commands..."); } private void Update() { float deltaTime = Time.deltaTime; try { RunGate.Tick(deltaTime); } catch { } float realtimeSinceStartup = Time.realtimeSinceStartup; lock (DelayedLock) { for (int num = DelayedActions.Count - 1; num >= 0; num--) { if (!(DelayedActions[num].due > realtimeSinceStartup)) { Action item = DelayedActions[num].action; DelayedActions.RemoveAt(num); if (item != null) { MainThreadQueue.Enqueue(item); } } } } int count = MainThreadQueue.Count; int num2 = ((count > 2) ? Math.Min(count, 256) : 16); int num3 = 0; Action result; while (num3 < num2 && MainThreadQueue.TryDequeue(out result)) { num3++; try { result(); } catch (Exception ex) { ModLog.Error("Main thread action failed: " + ex.Message); } } } private void BindConfig() { _portConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Port", 8080, "Local WebSocket port for TokControl commands (ws://127.0.0.1:PORT/)"); _logToUnityConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogToUnityConsole", true, "Mirror TokControl bridge logs to Unity debug console"); _defaultGhostEnemyConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Gameplay", "DefaultGhostEnemy", "Hidden", "Enemy name used for spawn_ghost when no name is provided (e.g. Hidden, Robe, Hunter)"); } internal static bool ShouldLogToUnity() { return Instance?._logToUnityConfig?.Value ?? true; } private void OnDestroy() { try { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } _server?.Dispose(); ModLog.Info("TokControl_REPO_Tiktoklive shut down"); } } public static class PluginInfo { public const string PLUGIN_GUID = "com.tokcontrol.repobridge"; public const string PLUGIN_NAME = "TokControl_REPO_Tiktoklive"; public const string PLUGIN_VERSION = "1.3.91"; } } namespace TokControlREPOBridge.Util { internal static class BurstCoalescer { private const float QuietSeconds = 0.45f; private static readonly Dictionary<string, Action> FlushActions = new Dictionary<string, Action>(); internal static void Debounce(string key, Action onFlush, Action? onTouch = null) { onTouch?.Invoke(); FlushActions[key] = onFlush; EffectTimerHost.Instance.Stop(key); EffectTimerHost.Instance.RunForSeconds(key, 0.45f, delegate { }, delegate { if (!FlushActions.TryGetValue(key, out Action value)) { return; } FlushActions.Remove(key); try { value(); } catch (Exception ex) { ModLog.Warn("Burst flush '" + key + "' failed: " + ex.Message); } }); } } public static class GameNotifier { public static void AnnounceSpawn(string user, string target, int count, string kind) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string text2 = (string.IsNullOrWhiteSpace(target) ? "item" : target.Trim()); string text3 = ((count > 1) ? $" x{count}" : ""); PostAnnouncement(text + " activates '" + text2 + text3 + "'", 4.5f); } public static void AnnounceEvent(string user, string eventId) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string label = EventLangCatalog.GetLabel(eventId); PostAnnouncement(text + " activates '" + label + "'", 3.5f); } public static void AnnounceCustom(string user, string message, float seconds = 4.5f) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string text2 = (string.IsNullOrWhiteSpace(message) ? "event" : message.Trim()); if (text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { PostAnnouncement(text2, seconds); } else { PostAnnouncement(text + " → " + text2, seconds); } } private static void PostAnnouncement(string line, float seconds = 3f) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(line)) { PostTruck(line); PostMission(line, new Color(1f, 0.45f, 0.15f), Color.white, Math.Max(2f, seconds)); } } private static void PostTruck(string message) { try { if ((Object)(object)TruckScreenText.instance == (Object)null) { ModLog.Debug("TruckScreenText not ready — skip monitor message"); } else { TruckScreenText.instance.MessageSendCustom("", "{arrowright}" + message + "{arrowleft}", 0); } } catch (Exception ex) { ModLog.Debug("Truck notify failed: " + ex.Message); } } private static void PostMission(string text, Color colorA, Color colorB, float seconds) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)MissionUI.instance == (Object)null)) { MissionUI.instance.MissionText(text, colorA, colorB, seconds); } } catch (Exception ex) { ModLog.Debug("Mission notify failed: " + ex.Message); } } } public static class MainThreadDispatcher { public static bool IsReady => (Object)(object)Plugin.Instance != (Object)null; public static void Enqueue(Action action) { Plugin.EnqueueMainThread(action); } public static void EnqueueDelayed(Action action, float delaySeconds) { Plugin.EnqueueMainThreadDelayed(action, delaySeconds); } } public static class SimpleJson { public static string? GetString(string json, string key) { if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key)) { return null; } string value = "\"" + key + "\""; int num = json.IndexOf(value, StringComparison.OrdinalIgnoreCase); if (num < 0) { return null; } num = json.IndexOf(':', num); if (num < 0) { return null; } for (num++; num < json.Length && char.IsWhiteSpace(json[num]); num++) { } if (num >= json.Length) { return null; } if (json[num] == '"') { num++; int num2 = num; while (num < json.Length) { if (json[num] == '\\') { num += 2; continue; } if (json[num] == '"') { break; } num++; } return json.Substring(num2, num - num2); } int num3 = num; for (; num < json.Length && json[num] != ',' && json[num] != '}'; num++) { } return json.Substring(num3, num - num3).Trim().Trim('"'); } public static int? GetInt(string json, string key) { string text = GetString(json, key); if (text != null && int.TryParse(text, out var result)) { return result; } return null; } public static string Escape(string value) { return (value ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") .Replace("\r", "\\r"); } public static string CommandResult(bool success, string message, string? detail = null) { if (!string.IsNullOrEmpty(detail)) { return "{\"success\":" + (success ? "true" : "false") + ",\"message\":\"" + Escape(message) + "\",\"detail\":\"" + Escape(detail) + "\"}"; } return "{\"success\":" + (success ? "true" : "false") + ",\"message\":\"" + Escape(message) + "\"}"; } public static string EffectPayload(string eventId, string user, int playerViewId = 0, int count = 1, string? namedPlayer = null) { int num = Math.Max(1, Math.Min(count, 100)); string text = Escape(namedPlayer ?? ""); return $"{{\"count\":{num},\"eventId\":\"{Escape(eventId)}\",\"user\":\"{Escape(user)}\",\"playerViewId\":{playerViewId},\"namedPlayer\":\"{text}\"}}"; } public static bool TryParseEffectPayload(string json, out string eventId, out string user) { int playerViewId; int count; string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId) { int count; string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId, out int count) { string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId, out int count, out string namedPlayer) { eventId = GetString(json, "eventId") ?? GetString(json, "cmd") ?? ""; user = GetString(json, "user") ?? "viewer"; playerViewId = GetInt(json, "playerViewId").GetValueOrDefault(); count = Math.Max(1, Math.Min(GetInt(json, "count") ?? 1, 100)); namedPlayer = GetString(json, "namedPlayer") ?? GetString(json, "targetPlayer") ?? ""; return !string.IsNullOrWhiteSpace(eventId); } public static string SpawnPayload(string cmd, string name, int count, string user, int playerViewId = 0) { return $"{{\"count\":{count},\"cmd\":\"{Escape(cmd)}\",\"name\":\"{Escape(name)}\",\"user\":\"{Escape(user)}\",\"playerViewId\":{playerViewId}}}"; } public static bool TryParseSpawnPayload(string json, out string cmd, out string name, out int count, out string user) { int playerViewId; return TryParseSpawnPayload(json, out cmd, out name, out count, out user, out playerViewId); } public static bool TryParseSpawnPayload(string json, out string cmd, out string name, out int count, out string user, out int playerViewId) { cmd = GetString(json, "cmd") ?? ""; name = GetString(json, "name") ?? ""; count = GetInt(json, "count") ?? 1; user = GetString(json, "user") ?? "viewer"; playerViewId = GetInt(json, "playerViewId").GetValueOrDefault(); return !string.IsNullOrWhiteSpace(cmd); } } } namespace TokControlREPOBridge.Ui { internal static class EnemyRoomCounter { private const float RoomRadius = 22f; internal static int CountInCurrentRooms() { return HudStatsProvider.GetEnemyCount(); } internal static int ScanLiveCountInCurrentRooms() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!IsInGameplayLevel()) { return 0; } List<Vector3> playerRoomAnchors = HudRoomHelper.GetPlayerRoomAnchors(); if (playerRoomAnchors.Count == 0) { return 0; } int num = 0; EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); foreach (EnemyParent val in array) { if (IsLiveEnemy(val) && IsNearAnyAnchor(((Component)val).transform.position, playerRoomAnchors, 22f)) { num++; } } return num; } private static bool IsInGameplayLevel() { try { if (SemiFunc.MenuLevel()) { return false; } return SemiFunc.RunIsLevel(); } catch { return (Object)(object)RunManager.instance != (Object)null; } } private static bool IsNearAnyAnchor(Vector3 position, List<Vector3> anchors, float radius) { //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) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; foreach (Vector3 anchor in anchors) { if (HorizontalDistanceSqr(position, anchor) <= num) { return true; } } return false; } private static bool IsLiveEnemy(EnemyParent parent) { if ((Object)(object)parent == (Object)null || !((Component)parent).gameObject.activeInHierarchy) { return false; } Enemy componentInChildren = ((Component)parent).GetComponentInChildren<Enemy>(true); if ((Object)(object)componentInChildren == (Object)null || !((Component)componentInChildren).gameObject.activeInHierarchy) { return false; } if (ReadBool(parent, "despawned")) { return false; } if (ReadBool(parent, "disabled")) { return false; } if (ReadBool(componentInChildren, "disabled")) { return false; } if (ReadBool(componentInChildren, "dead")) { return false; } if (ReadBool(componentInChildren, "isDead")) { return false; } if (ReadBool(componentInChildren, "despawned")) { return false; } return true; } private static bool ReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } } catch { } return false; } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) a.y = 0f; b.y = 0f; Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; } } internal static class HudRoomHelper { private const float RoomRadius = 22f; internal static bool IsInCurrentRoom(Vector3 position) { //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_0027: 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) List<Vector3> playerRoomAnchors = GetPlayerRoomAnchors(); if (playerRoomAnchors.Count == 0) { return false; } float num = 484f; foreach (Vector3 item in playerRoomAnchors) { if (HorizontalDistanceSqr(position, item) <= num) { return true; } } return false; } internal static List<Vector3> GetPlayerRoomAnchors() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); try { List<LevelPoint> list2 = SemiFunc.LevelPointsGetInPlayerRooms(); if (list2 != null) { foreach (LevelPoint item in list2) { if ((Object)(object)item != (Object)null) { list.Add(((Component)item).transform.position); } } } } catch { } if (list.Count > 0) { return list; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null) { list.Add(((Component)val).transform.position); } return list; } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) a.y = 0f; b.y = 0f; Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; } } internal static class HudStatsProvider { private const float MapInterval = 0.5f; private const float CartInterval = 0.55f; private const float CosmeticInterval = 1.35f; private const float EnemyInterval = 0.6f; private static readonly Dictionary<string, string> RarityColors = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["common"] = "#55FF55", ["uncommon"] = "#5599FF", ["rare"] = "#BB55FF", ["ultrarare"] = "#FF8800", ["ultra"] = "#FF8800", ["ultra rare"] = "#FF8800" }; private static readonly string[] RarityOrder = new string[4] { "common", "uncommon", "rare", "ultrarare" }; private static float _cachedMap; private static float _cachedCart; private static int _cachedEnemies; private static string _cachedCosmetics = string.Empty; private static bool _hasCosmetics; private static float _mapNext; private static float _cartNext; private static float _cosmeticNext; private static float _enemyNext; internal static void InvalidateCache() { _mapNext = 0f; _cartNext = 0f; _cosmeticNext = 0f; _enemyNext = 0f; } internal static void TickCache() { float unscaledTime = Time.unscaledTime; if (unscaledTime >= _mapNext) { _cachedMap = ScanMapValue(); _mapNext = unscaledTime + 0.5f; } if (unscaledTime >= _cartNext) { _cachedCart = ScanCartValue(); _cartNext = unscaledTime + 0.55f; } if (unscaledTime >= _cosmeticNext) { _hasCosmetics = ScanCosmeticIconLine(out _cachedCosmetics); _cosmeticNext = unscaledTime + 1.35f; } if (unscaledTime >= _enemyNext) { _cachedEnemies = EnemyRoomCounter.ScanLiveCountInCurrentRooms(); _enemyNext = unscaledTime + 0.6f; } } internal static float GetMapValue() { return _cachedMap; } internal static float GetCartValue() { return _cachedCart; } internal static int GetEnemyCount() { return _cachedEnemies; } internal static bool TryBuildCosmeticIconLine(out string line) { line = _cachedCosmetics; return _hasCosmetics; } private static float ScanMapValue() { float num = 0f; HashSet<PhysGrabObject> cartPhysObjects = GetCartPhysObjects(); ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); foreach (ValuableObject val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled) { PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>(); if (!((Object)(object)component != (Object)null) || !cartPhysObjects.Contains(component)) { num += Mathf.Max(0f, val.dollarValueCurrent); } } } return num; } private static float ScanCartValue() { float num = 0f; PhysGrabCart[] allCarts = CartHelper.GetAllCarts(); foreach (PhysGrabCart cart in allCarts) { foreach (PhysGrabObject cartItemObject in CartHelper.GetCartItemObjects(cart)) { if (!((Object)(object)cartItemObject == (Object)null)) { ValuableObject component = ((Component)cartItemObject).GetComponent<ValuableObject>(); if ((Object)(object)component != (Object)null) { num += Mathf.Max(0f, component.dollarValueCurrent); } } } } return num; } private static bool ScanCosmeticIconLine(out string line) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); CosmeticWorldObject[] array = Object.FindObjectsOfType<CosmeticWorldObject>(); foreach (CosmeticWorldObject val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && !IsCosmeticBoxExtracted(val) && HudRoomHelper.IsInCurrentRoom(((Component)val).transform.position)) { string text = NormalizeRarity(ReadCosmeticRarity(val)); if (!string.IsNullOrWhiteSpace(text)) { hashSet.Add(text); } } } if (hashSet.Count == 0) { line = string.Empty; return false; } StringBuilder stringBuilder = new StringBuilder(); string[] rarityOrder = RarityOrder; foreach (string text2 in rarityOrder) { if (hashSet.Contains(text2)) { string value; string text3 = (RarityColors.TryGetValue(text2, out value) ? value : "#DDDDDD"); if (stringBuilder.Length > 0) { stringBuilder.Append(' '); } stringBuilder.Append("<color=" + text3 + ">■</color>"); } } line = stringBuilder.ToString(); return line.Length > 0; } private static bool IsCosmeticBoxExtracted(CosmeticWorldObject box) { try { CosmeticWorldObjectHealth component = ((Component)box).GetComponent<CosmeticWorldObjectHealth>(); if ((Object)(object)component != (Object)null) { FieldInfo field = typeof(CosmeticWorldObjectHealth).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(component); if (value is float num && num <= 0f) { return true; } if (value is int num2 && num2 <= 0) { return true; } } } } catch { } string text = ((Object)((Component)box).gameObject).name.ToLowerInvariant(); if (!text.Contains("extract") && !text.Contains("broken")) { return text.Contains("opened"); } return true; } private static string ReadCosmeticRarity(CosmeticWorldObject box) { try { FieldInfo field = typeof(CosmeticWorldObject).GetField("cosmeticRarity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(box); if (value != null) { return value.ToString() ?? string.Empty; } } } catch { } return GuessRarityFromName(((Object)((Component)box).gameObject).name); } private static string NormalizeRarity(string rarity) { string text = rarity.Replace("_", " ").Trim().ToLowerInvariant(); if (text.Contains("ultra")) { return "ultrarare"; } if (text.Contains("uncommon")) { return "uncommon"; } if (text.Contains("common")) { return "common"; } if (text.Contains("rare")) { return "rare"; } return text; } private static string GuessRarityFromName(string name) { string text = name.ToLowerInvariant(); if (text.Contains("ultra")) { return "ultrarare"; } if (text.Contains("uncommon")) { return "uncommon"; } if (text.Contains("rare")) { return "rare"; } if (text.Contains("common")) { return "common"; } return string.Empty; } private static HashSet<PhysGrabObject> GetCartPhysObjects() { HashSet<PhysGrabObject> hashSet = new HashSet<PhysGrabObject>(); PhysGrabCart[] allCarts = CartHelper.GetAllCarts(); foreach (PhysGrabCart cart in allCarts) { foreach (PhysGrabObject cartItemObject in CartHelper.GetCartItemObjects(cart)) { if ((Object)(object)cartItemObject != (Object)null) { hashSet.Add(cartItemObject); } } } return hashSet; } } internal sealed class MapValueAnimator { private const float ScanDuration = 0.85f; private const float LossFadeDuration = 1.75f; private float _mapValue; private float _lossAmount; private float _lossFadeTimer; private float _scanTimer; private float _scanMax; private bool _scanReady; internal bool IsScanReady => _scanReady; internal bool IsAnimating => _lossFadeTimer > 0f; internal void BeginLevel() { _mapValue = 0f; _lossAmount = 0f; _lossFadeTimer = 0f; _scanTimer = 0.85f; _scanMax = 0f; _scanReady = false; } internal void EndLevel() { _scanReady = false; _scanTimer = 0f; _lossAmount = 0f; _lossFadeTimer = 0f; } internal void Tick(float actualValue, float deltaTime) { if (!_scanReady) { _scanMax = Mathf.Max(_scanMax, actualValue); _scanTimer -= deltaTime; if (_scanTimer <= 0f) { _mapValue = _scanMax; _scanReady = true; } return; } if (actualValue > _mapValue + 0.5f) { _mapValue = actualValue; return; } if (actualValue < _mapValue - 0.5f) { _lossAmount = _mapValue - actualValue; _mapValue = actualValue; _lossFadeTimer = 1.75f; } else { _mapValue = actualValue; } if (_lossFadeTimer > 0f) { _lossFadeTimer -= deltaTime; if (_lossFadeTimer <= 0f) { _lossAmount = 0f; _lossFadeTimer = 0f; } } } internal string? BuildMapLine() { if (!_scanReady) { return null; } if (_lossAmount > 0.5f && _lossFadeTimer > 0f) { float num = Mathf.Clamp01(_lossFadeTimer / 1.75f); string arg = Color32ToHex(byte.MaxValue, (byte)Mathf.RoundToInt(77f * num), (byte)Mathf.RoundToInt(77f * num)); return $"<color=#{arg}>-${_lossAmount:N0}</color> MAP: ${_mapValue:N0}"; } return $"MAP: ${_mapValue:N0}"; } private static string Color32ToHex(byte r, byte g, byte b) { return $"{r:X2}{g:X2}{b:X2}"; } } internal sealed class TokControlStatusHud : MonoBehaviour { private const float RefreshInterval = 0.4f; private const float LossRefreshInterval = 0.08f; private const float RepositionInterval = 1.5f; private const float LineHeight = 14f; private const float FontSize = 13f; private static TokControlStatusHud? _instance; private readonly MapValueAnimator _mapAnimator = new MapValueAnimator(); private GameObject? _panelRoot; private TextMeshProUGUI? _label; private RectTransform? _panelRt; private RectTransform? _gameHudRt; private RectTransform? _taxHaulRt; private float _refreshTimer; private float _repositionTimer; private string _lastText = string.Empty; private int _trackedLevel = -1; private bool _wasInLevel; internal static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("TokControlStatusHud"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent<TokControlStatusHud>(); } } private void Update() { bool flag = IsInPlayableLevel(); if (flag && !_wasInLevel) { _trackedLevel = GetLevelId(); _mapAnimator.BeginLevel(); HudStatsProvider.InvalidateCache(); } else if (flag) { int levelId = GetLevelId(); if (levelId != _trackedLevel) { _trackedLevel = levelId; _mapAnimator.BeginLevel(); HudStatsProvider.InvalidateCache(); } } else if (_wasInLevel) { _trackedLevel = -1; _mapAnimator.EndLevel(); HudStatsProvider.InvalidateCache(); } _wasInLevel = flag; if (!ShouldShowHud()) { HidePanel(); return; } if (!EnsurePanel()) { HidePanel(); return; } _repositionTimer -= Time.unscaledDeltaTime; if (_repositionTimer <= 0f) { _repositionTimer = 1.5f; RepositionBelowHudStack(); } HudStatsProvider.TickCache(); _mapAnimator.Tick(HudStatsProvider.GetMapValue(), Time.unscaledDeltaTime); float refreshTimer = (_mapAnimator.IsAnimating ? 0.08f : 0.4f); _refreshTimer -= Time.unscaledDeltaTime; if (!(_refreshTimer > 0f) || !((Object)(object)_panelRoot != (Object)null) || !_panelRoot.activeSelf) { _refreshTimer = refreshTimer; string text = BuildStatusText(); if (!(text == _lastText) || !((Object)(object)_panelRoot != (Object)null) || !_panelRoot.activeSelf) { _lastText = text; ((TMP_Text)_label).SetText(text, true); _panelRoot.SetActive(true); } } } private string BuildStatusText() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) float cartValue = HudStatsProvider.GetCartValue(); int enemyCount = HudStatsProvider.GetEnemyCount(); string line; bool flag = HudStatsProvider.TryBuildCosmeticIconLine(out line); int num = 2; if (_mapAnimator.IsScanReady) { num++; } num++; if (flag) { num++; } if ((Object)(object)_panelRt != (Object)null) { _panelRt.sizeDelta = new Vector2(168f, 14f * (float)num); } StringBuilder stringBuilder = new StringBuilder(); string value = _mapAnimator.BuildMapLine(); if (!string.IsNullOrEmpty(value)) { stringBuilder.AppendLine(value); } stringBuilder.AppendLine($"C.A.R.T.: ${cartValue:N0}"); stringBuilder.AppendLine($"MON: {enemyCount}"); if (flag) { stringBuilder.Append(line); } return stringBuilder.ToString().TrimEnd(); } private static bool IsInPlayableLevel() { try { return !SemiFunc.MenuLevel() && SemiFunc.RunIsLevel(); } catch { return (Object)(object)RunManager.instance != (Object)null; } } private static int GetLevelId() { try { Level val = RunManager.instance?.levelCurrent; return ((Object)(object)val == (Object)null) ? (-1) : ((object)val).GetHashCode(); } catch { return -1; } } private static bool ShouldShowHud() { if (!IsInPlayableLevel()) { return false; } if (IsMapOpen()) { return false; } return true; } private static bool IsMapOpen() { try { if (SemiFunc.InputHold((InputKey)8)) { return true; } } catch { } if (Input.GetKey((KeyCode)9)) { return true; } try { if ((Object)(object)MapToolController.instance == (Object)null) { return false; } FieldInfo field = typeof(MapToolController).GetField("mapToggled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(MapToolController.instance); } } catch { } return false; } private bool EnsurePanel() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelRoot != (Object)null && (Object)(object)_label != (Object)null && (Object)(object)_panelRt != (Object)null) { return true; } GameObject val = GameObject.Find("Game Hud"); GameObject val2 = GameObject.Find("Tax Haul"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } TMP_Text component = val2.GetComponent<TMP_Text>(); if ((Object)(object)component == (Object)null || (Object)(object)component.font == (Object)null) { return false; } _gameHudRt = val.GetComponent<RectTransform>(); _taxHaulRt = val2.GetComponent<RectTransform>(); _panelRoot = new GameObject("TokControl Status HUD"); _panelRoot.SetActive(false); _label = _panelRoot.AddComponent<TextMeshProUGUI>(); ((TMP_Text)_label).font = component.font; ((TMP_Text)_label).fontSize = 13f; ((TMP_Text)_label).lineSpacing = 0f; ((TMP_Text)_label).paragraphSpacing = 0f; ((TMP_Text)_label).enableWordWrapping = false; ((TMP_Text)_label).alignment = (TextAlignmentOptions)260; ((TMP_Text)_label).horizontalAlignment = (HorizontalAlignmentOptions)4; ((TMP_Text)_label).verticalAlignment = (VerticalAlignmentOptions)256; ((Graphic)_label).color = new Color(0.79f, 0.91f, 0.9f, 1f); ((TMP_Text)_label).richText = true; ((TMP_Text)_label).margin = new Vector4(0f, 0f, 0f, 0f); _panelRoot.transform.SetParent(val.transform, false); _panelRt = _panelRoot.GetComponent<RectTransform>(); _panelRt.anchorMin = new Vector2(1f, 1f); _panelRt.anchorMax = new Vector2(1f, 1f); _panelRt.pivot = new Vector2(1f, 1f); _panelRt.sizeDelta = new Vector2(168f, 56f); return true; } private void RepositionBelowHudStack() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelRt == (Object)null) { return; } if ((Object)(object)_gameHudRt == (Object)null || (Object)(object)_taxHaulRt == (Object)null) { GameObject val = GameObject.Find("Game Hud"); GameObject obj = GameObject.Find("Tax Haul"); RectTransform val2 = ((obj != null) ? obj.GetComponent<RectTransform>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } _gameHudRt = val.GetComponent<RectTransform>(); _taxHaulRt = val2; } float num = _taxHaulRt.anchoredPosition.y; TMP_Text[] componentsInChildren = ((Component)_gameHudRt).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val3 in componentsInChildren) { if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)_label || ((Object)((Component)val3).gameObject).name.StartsWith("TokControl") || !((Component)val3).gameObject.activeInHierarchy) { continue; } RectTransform component = ((Component)val3).GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null) && !(component.anchorMax.x < 0.55f)) { float num2 = component.anchoredPosition.y - Mathf.Max(component.sizeDelta.y, val3.fontSize * 0.85f); if (num2 < num) { num = num2; } } } _panelRt.anchoredPosition = new Vector2(-12f, num - 4f); } private void HidePanel() { if ((Object)(object)_panelRoot != (Object)null) { _panelRoot.SetActive(false); } _lastText = string.Empty; } } } namespace TokControlREPOBridge.Network { public static class EffectRelay { private const string EventName = "TokControl_EffectRelay_v1"; private static NetworkedEvent? _relayEvent; public static void Initialize(GameActions actions) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown _relayEvent = new NetworkedEvent("TokControl_EffectRelay_v1", (Action<EventData>)OnRelayReceived); ModLog.Info("Effect relay initialized (client → host)"); } public static CommandResult ExecuteEffect(string eventId, string user, int count = 1) { return StreamEventRunner.Execute(eventId, user, count); } public static CommandResult RelayKnownEvent(string eventId, string user, int count = 1, int playerViewId = 0, string? namedPlayer = null) { return RelayToHost(eventId, user, playerViewId, count, namedPlayer); } private static CommandResult RelayToHost(string eventId, string user, int playerViewId, int count, string? namedPlayer = null) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (_relayEvent == null) { return CommandResult.Fail("relay_not_ready"); } count = Math.Max(1, Math.Min(count, 100)); try { string text = SimpleJson.EffectPayload(eventId, user, playerViewId, count, namedPlayer); _relayEvent.RaiseEvent((object)text, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); ModLog.Info($"Effect relayed to host: {eventId} x{count} for @{user} (view={playerViewId} name={namedPlayer})"); return CommandResult.Ok("relayed_to_host", $"Effect {eventId} x{count} sent to lobby host"); } catch (Exception ex) { ModLog.Error("Effect relay failed: " + ex.Message); return CommandResult.Fail("relay_failed:" + ex.Message); } } private static void OnRelayReceived(EventData eventData) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { ModLog.Debug("Effect relay received on non-host — ignored"); return; } try { string text = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(text)) { ModLog.Warn("Effect relay payload empty"); return; } if (!SimpleJson.TryParseEffectPayload(text, out string eventId, out string user, out int playerViewId, out int count, out string namedPlayer)) { ModLog.Warn("Effect relay payload invalid"); return; } ModLog.Info($"Host executing effect relay: {eventId} x{count} for @{user} view={playerViewId} name={namedPlayer}"); MainThreadDispatcher.Enqueue(delegate { string commandLine; if (!string.IsNullOrWhiteSpace(namedPlayer)) { StreamEventRunner.Execute(eventId, user ?? "viewer", count, null, namedPlayer); } else if (!EventCommandCatalog.TryGetCommandLine(eventId, out commandLine)) { ModLog.Warn("Host relay unknown event: " + eventId); } else { PlayerAvatar targetPlayer = null; if (playerViewId > 0) { try { targetPlayer = SemiFunc.PlayerAvatarGetFromPhotonID(playerViewId); } catch { } } StreamEventRunner.ExecuteLocal(eventId, commandLine, user ?? "viewer", count, targetPlayer); } }); } catch (Exception ex) { ModLog.Error("Effect relay handler error: " + ex.Message); } } } public static class SpawnRelay { private const string EventName = "TokControl_SpawnRelay_v1"; private static NetworkedEvent? _relayEvent; private static GameActions? _actions; public static void Initialize(GameActions actions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _actions = actions; _relayEvent = new NetworkedEvent("TokControl_SpawnRelay_v1", (Action<EventData>)OnRelayReceived); ModLog.Info("Spawn relay initialized (client → host)"); } public static CommandResult ExecuteSpawn(string cmd, string name, int count, string user) { if (_actions == null) { return CommandResult.Fail("relay_not_ready"); } if (!MainThreadDispatcher.IsReady) { return CommandResult.Fail("game_not_ready"); } if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); int playerViewId = 0; try { playerViewId = (((Object)(object)val?.photonView != (Object)null) ? val.photonView.ViewID : 0); } catch { } if (SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.IsMultiplayer()) { return ExecuteLocally(cmd, name, count, user, val); } return RelayToHost(cmd, name, count, user, playerViewId); } private static CommandResult RelayToHost(string cmd, string name, int count, string user, int playerViewId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (_relayEvent == null) { return CommandResult.Fail("relay_not_ready"); } try { string text = SimpleJson.SpawnPayload(cmd, name, count, user, playerViewId); _relayEvent.RaiseEvent((object)text, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); ModLog.Info($"Relayed to host: {cmd} {name} x{count} for @{user} (view={playerViewId})"); return CommandResult.Ok("relayed_to_host", "Spawn sent to lobby host — host must have this mod installed"); } catch (Exception ex) { ModLog.Error("Relay failed: " + ex.Message); return CommandResult.Fail("relay_failed:" + ex.Message); } } private static void OnRelayReceived(EventData eventData) { if (_actions == null) { return; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { ModLog.Debug("Relay received on non-host — ignored"); return; } try { string text = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(text)) { ModLog.Warn("Relay payload empty"); return; } if (!SimpleJson.TryParseSpawnPayload(text, out string cmd, out string name, out int count, out string user, out int playerViewId)) { ModLog.Warn("Relay payload invalid"); return; } ModLog.Info($"Host executing relay: {cmd} {name} x{count} for @{user} view={playerViewId}"); MainThreadDispatcher.Enqueue(delegate { PlayerAvatar targetPlayer = null; if (playerViewId > 0) { try { targetPlayer = SemiFunc.PlayerAvatarGetFromPhotonID(playerViewId); } catch { } } ExecuteLocally(cmd, name, count, user ?? "viewer", targetPlayer); }); } catch (Exception ex) { ModLog.Error("Relay handler error: " + ex.Message); } } private static CommandResult ExecuteLocally(string cmd, string name, int count, string user, PlayerAvatar? targetPlayer) { if (_actions == null) { return CommandResult.Fail("actions_not_ready"); } count = Math.Max(1, Math.Min(count, 100)); cmd = cmd.Trim().ToLowerInvariant(); EventContext.SetTarget(targetPlayer ?? SemiFunc.PlayerAvatarLocal()); try { switch (cmd) { case "spawn_item": case "spawnitem": case "item": return _actions.SpawnItemLocal(name, count, user); case "spawnghost": case "spawn_ghost": case "ghost": return _actions.SpawnEnemyLocal(name, count, user); case "spawnenemy": case "spawn_enemy": case "enemy": return _actions.SpawnEnemyLocal(name, count, user); case "spawn_valuable": case "spawnvaluable": case "valuable": return _actions.SpawnValuableLocal(name, count, user); case "spawnbatch": case "spawn_batch": case "batch": return _actions.SpawnBatchLocal(name, user); default: return CommandResult.Fail("unknown_spawn_cmd:" + cmd); } } finally { EventContext.Clear(); } } } internal static class SpeakBroadcast { private const string EventName = "TokControl_SpeakBroadcast_v1"; private static NetworkedEvent? _event; private static bool _handling; public static void Initialize() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown _event = new NetworkedEvent("TokControl_SpeakBroadcast_v1", (Action<EventData>)OnReceived); ModLog.Info("Speak broadcast initialized"); } public static void Broadcast(string message) { if (!string.IsNullOrWhiteSpace(message)) { SpeakHelper.ForceSpeakNow(message); RaiseOthers(message); } } public static void RaiseOthers(string message) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(message) || _event == null) { return; } try { if (SemiFunc.IsMultiplayer()) { _event.RaiseEvent((object)message, NetworkingEvents.RaiseOthers, SendOptions.SendReliable); } } catch (Exception ex) { ModLog.Debug("Speak broadcast failed: " + ex.Message); } } private static void OnReceived(EventData eventData) { if (_handling) { return; } string raw = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(raw)) { return; } MainThreadDispatcher.Enqueue(delegate { _handling = true; try { SpeakHelper.ForceSpeakNow(raw); } finally { _handling = false; } }); } } public sealed class WebSocketServer : IDisposable { private readonly int _preferredPort; private readonly CommandProcessor _processor; private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private HttpListener? _listener; private Task? _acceptTask; public int Port { get; private set; } public WebSocketServer(int port, CommandProcessor processor) { _preferredPort = ((port > 0) ? port : 8080); Port = _preferredPort; _processor = processor; } public void Start() { int[] array = BuildPortCandidates(_preferredPort); Exception ex = null; int[] array2 = array; foreach (int num in array2) { HttpListener httpListener = null; try { httpListener = new HttpListener(); httpListener.Prefixes.Add($"http://127.0.0.1:{num}/"); httpListener.Start(); _listener = httpListener; Port = num; _acceptTask = Task.Run(() => AcceptLoopAsync(_cts.Token)); if (num != _preferredPort) { ModLog.Warn($"Port {_preferredPort} was busy — TokControl bridge moved to ws://127.0.0.1:{num}/"); ModLog.Warn($"Set TokControl Connection URL to: ws://127.0.0.1:{num}/"); } else { ModLog.Info($"HTTP/WebSocket listener started on port {num} (127.0.0.1 only)"); } return; } catch (Exception ex2) { ex = ex2; try { httpListener?.Close(); } catch { } ModLog.Warn($"Could not bind 127.0.0.1:{num} — {ex2.Message}"); } } throw new InvalidOperationException("TokControl bridge failed to bind any port (tried " + string.Join(", ", array) + "). Last error: " + ex?.Message); } private static int[] BuildPortCandidates(int preferred) { List<int> list = new List<int> { preferred }; int[] array = new int[5] { 8080, 8082, 8090, 18080, 28080 }; foreach (int item in array) { if (!list.Contains(item)) { list.Add(item); } } return list.ToArray(); } private async Task AcceptLoopAsync(CancellationToken ct) { while (!ct.IsCancellationRequested && _listener != null && _listener.IsListening) { HttpListenerContext context = null; try { context = await _listener.GetContextAsync().ConfigureAwait(continueOnCapturedContext: false); } catch (HttpListenerException) when (ct.IsCancellationRequested) { break; } catch (ObjectDisposedException) { break; } catch (Exception ex3) { ModLog.Warn("Accept error: " + ex3.Message); continue; } Task.Run(() => HandleContextAsync(context, ct), ct); } } private async Task HandleContextAsync(HttpListenerContext context, CancellationToken ct) { _ = 3; try { if (context.Request.IsWebSocketRequest) { await HandleWebSocketAsync((await context.AcceptWebSocketAsync(null).ConfigureAwait(continueOnCapturedContext: false)).WebSocket, ct).ConfigureAwait(continueOnCapturedContext: false); return; } string text = context.Request.Url?.AbsolutePath ?? "/"; string s; if (text.Equals("/health", StringComparison.OrdinalIgnoreCase)) { s = "{\"ok\":true,\"mod\":\"TokControl_REPO_Tiktoklive\",\"version\":\"1.3.91\",\"port\":" + Port + "}"; } else if (context.Request.HttpMethod == "POST") { using StreamReader reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding); string raw = await reader.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false); CommandResult commandResult = _processor.Process(raw); s = commandResult.ToJson(); } else { s = "{\"ok\":true,\"mod\":\"TokControl_REPO_Tiktoklive\",\"hint\":\"Connect via WebSocket ws://127.0.0.1:" + Port + "/\"}"; } byte[] bytes = Encoding.UTF8.GetBytes(s); context.Response.StatusCode = 200; context.Response.ContentType = "application/json"; context.Response.ContentLength64 = bytes.Length; await context.Response.OutputStream.WriteAsync(bytes, 0, bytes.Length, ct).ConfigureAwait(continueOnCapturedContext: false); context.Response.Close(); } catch (Exception ex) { ModLog.Warn("Request handler error: " + ex.Message); try { context.Response.StatusCode = 500; context.Response.Close(); } catch { } } } private async Task HandleWebSocketAsync(WebSocket socket, CancellationToken ct) { byte[] buffer = new byte[8192]; ModLog.Info("WebSocket client connected"); try { while (socket.State == WebSocketState.Open && !ct.IsCancellationRequested) { WebSocketReceiveResult webSocketReceiveResult = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), ct).ConfigureAwait(continueOnCapturedContext: false); if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close) { break; } if (webSocketReceiveResult.MessageType != WebSocketMessageType.Text) { continue; } string message = Encoding.UTF8.GetString(buffer, 0, webSocketReceiveResult.Count); Task.Run(delegate { try { CommandResult commandResult = _processor.Process(message); byte[] bytes = Encoding.UTF8.GetBytes(commandResult.ToJson()); socket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, endOfMessage: true, ct); } catch (Exception ex3) { ModLog.Warn("WS message error: " + ex3.Message); } }, ct); } } catch (WebSocketException ex) { ModLog.Debug("WebSocket closed: " + ex.Message); } catch (Exception ex2) { ModLog.Warn("WebSocket error: " + ex2.Message); } finally { ModLog.Info("WebSocket client disconnected"); try { if (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseReceived) { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); } } catch { } socket.Dispose(); } } public void Dispose() { _cts.Cancel(); try { _listener?.Stop(); } catch { } try { _listener?.Close(); } catch { } _listener = null; _cts.Dispose(); } } } namespace TokControlREPOBridge.Logging { public static class ModLog { public static void Info(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.Log((object)Format(message)); } } public static void Warn(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.LogWarning((object)Format(message)); } } public static void Error(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.LogError((object)Format(message)); } } public static void Debug(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)Format(message)); } } private static string Format(string message) { return "[TokControl] " + message; } } } namespace TokControlREPOBridge.Commands { internal static class ArenaHelper { public static bool IsPlayerInCrownArenaBeforeStart(PlayerAvatar player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Arena instance = Arena.instance; if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null) { return false; } if (!IsBeforeCrownContestStart(instance)) { return false; } Vector3 arenaCenter = GetArenaCenter(instance); float num = Vector2.Distance(new Vector2(((Component)player).transform.position.x, ((Component)player).transform.position.z), new Vector2(arenaCenter.x, arenaCenter.z)); if (num < 18f) { return Mathf.Abs(((Component)player).transform.position.y - arenaCenter.y) < 10f; } return false; } public static bool IsContestMap() { if ((Object)(object)Arena.instance != (Object)null) { return true; } if ((Object)(object)ArenaRace.instance != (Object)null) { return true; } try { List<SpawnPoint> list = FindSpawnPoints(); if (list.Count < 2) { return false; } List<LevelPoint> list2 = null; try { list2 = SemiFunc.LevelPointsGetAll(); } catch { } return list2 == null || list2.Count <= 8; } catch { return false; } } public static Vector3? GetContestTeleportPosition(Vector3 avoidNear, Vector3 playerForward) { //IL_0010: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cf: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) if ((Object)(object)ArenaRace.instance != (Object)null) { Vector3? farthestSpawnPosition = GetFarthestSpawnPosition(avoidNear, 64f); if (farthestSpawnPosition.HasValue) { return farthestSpawnPosition; } Vector3? raceStartPosition = GetRaceStartPosition(avoidNear); if (raceStartPosition.HasValue && FarEnough(raceStartPosition.Value, avoidNear, 64f)) { return raceStartPosition; } Vector3? farthestRaceTrackPosition = GetFarthestRaceTrackPosition(avoidNear, 64f); if (farthestRaceTrackPosition.HasValue) { return farthestRaceTrackPosition; } Vector3? backwardOnTrack = GetBackwardOnTrack(avoidNear, playerForward, 64f); if (backwardOnTrack.HasValue && FarEnough(backwardOnTrack.Value, avoidNear, 64f)) { return backwardOnTrack; } return OffsetFarBehind(avoidNear, playerForward); } if ((Object)(object)Arena.instance != (Object)null && (Object)(object)ArenaRace.instance == (Object)null) { Vector3? result = GetFarthestSpawnPosition(avoidNear, 64f) ?? GetRandomSpawnPosition(avoidNear); if (result.HasValue) { return result; } } return (GetFarthestRaceTrackPosition(avoidNear, 64f) ?? GetRandomRaceTrackPosition(avoidNear)) ?? GetFarthestSpawnPosition(avoidNear, 64f) ?? GetRandomSpawnPosition(avoidNear); } public static Vector3? GetContestTeleportPosition(Vector3 avoidNear) { //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) return GetContestTeleportPosition(avoidNear, Vector3.back); } public static Vector3? GetRandomSpawnPosition(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = (from p in FindSpawnPoints() select ((Component)p).transform.position).ToList(); if (list.Count == 0) { return CartHelper.GetRandomPlayerSpawnPoint(avoidNear); } List<Vector3> list2 = list.Where(delegate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = pos - avoidNear; return ((Vector3)(ref val)).sqrMagnitude > 2.25f; }).ToList(); List<Vector3> list3 = ((list2.Count > 0) ? list2 : list); Vector3 position = list3[Random.Range(0, list3.Count)]; return KeepOnSurface(position, avoidNear); } private static Vector3? GetFarthestSpawnPosition(Vector3 avoidNear, float minSepSqr) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c1: 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_00db: 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_00e8: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = (from p in FindSpawnPoints() select ((Component)p).transform.position).ToList(); if (list.Count == 0) { Vector3? randomPlayerSpawnPoint = CartHelper.GetRandomPlayerSpawnPoint(avoidNear); if (randomPlayerSpawnPoint.HasValue && FarEnough(randomPlayerSpawnPoint.Value, avoidNear, minSepSqr)) { return KeepOnSurface(randomPlayerSpawnPoint.Value, avoidNear); } return null; } List<Vector3> list2 = list.OrderByDescending((Vector3 pos) => HorizontalSqr(pos, avoidNear)).ToList(); foreach (Vector3 item in list2) { if (FarEnough(item, avoidNear, minSepSqr)) { ModLog.Info("Contest teleport: farthest spawn / race start"); return KeepOnSurface(item, avoidNear); } } if (list2.Count > 0 && FarEnough(list2[0], avoidNear, 4f)) { return KeepOnSurface(list2[0], avoidNear); } return null; } public static Vector3 GetCrownArenaDropPosition() { //IL_0000: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) Vector3? randomSpawnPosition = GetRandomSpawnPosition(Vector3.zero); if (randomSpawnPosition.HasValue) { return randomSpawnPosition.Value; } Arena instance = Arena.instance; if ((Object)(object)instance == (Object)null) { return Vector3.zero; } Vector3 val = (((Object)(object)instance.crownTransform != (Object)null) ? instance.crownTransform.position : (((Object)(object)instance.crownPlatform != (Object)null) ? instance.crownPlatform.transform.position : ((Component)instance).transform.position)); return KeepOnSurface(val + Vector3.up * 1.2f); } public static Vector3 KeepOnSurface(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return KeepOnSurface(position, null); } public static Vector3 KeepOnSurface(Vector3 position, Vector3? ignoreNear) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position + Vector3.up * 8f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 24f, -1, (QueryTriggerInteraction)1); if (array != null && array.Length != 0) { Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val2 = array2[num]; if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !(((RaycastHit)(ref val2)).normal.y < 0.35f) && (!ignoreNear.HasValue || !(HorizontalSqr(((RaycastHit)(ref val2)).point, ignoreNear.Value) < 16f)) && !LooksLikeVehicle(((RaycastHit)(ref val2)).collider)) { return ((RaycastHit)(ref val2)).point + Vector3.up * 0.35f; } } } return position + Vector3.up * 0.4f; } private static bool LooksLikeVehicle(Collider col) { Transform val = ((Component)col).transform; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("vehicle") || text.Contains("scooter") || text.Contains("cart") || text.Contains("car") || text.Contains("buggy") || text.Contains("truck")) { return true; } val = val.parent; } return false; } private static bool FarEnough(Vector3 a, Vector3 b, float minSepSqr) { //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) return HorizontalSqr(a, b) >= minSepSqr; } private static float HorizontalSqr(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) float num = a.x - b.x; float num2 = a.z - b.z; return num * num + num2 * num2; } private static Vector3? GetRaceStartPosition(Vector3 avoidNear) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) List<SpawnPoint> list = FindSpawnPoints(); if (list.Count > 0) { return KeepOnSurface(((Component)list[0]).transform.position, avoidNear); } try { ArenaRace instance = ArenaRace.instance; if ((Object)(object)instance != (Object)null) { return KeepOnSurface(((Component)instance).transform.position + Vector3.up * 1.2f, avoidNear); } } catch { } return null; } private static Vector3? GetRaceStartPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetRaceStartPosition(Vector3.zero); } private static Vector3 OffsetFarBehind(Vector3 from, Vector3 forward) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0069: 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_001f: Unknown result type (might be due to invalid IL or missing references) forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.back; } ((Vector3)(ref forward)).Normalize(); Vector3 position = from - forward * Random.Range(28f, 42f) + Vector3.up * 1.2f; ModLog.Info("Contest teleport: far reverse offset"); return KeepOnSurface(position, from); } private static Vector3? GetBackwardOnTrack(Vector3 from, Vector3 forward, float minSepSqr) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.back; } ((Vector3)(ref forward)).Normalize(); try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType<ArenaRaceTrackPiece>(); if (array != null && array.Length != 0) { ArenaRaceTrackPiece val = null; float num = 1f; float num2 = 0f; ArenaRaceTrackPiece[] array2 = array; foreach (ArenaRaceTrackPiece val2 in array2) { if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled) { continue; } Vector3 val3 = ((Component)val2).transform.position - from; val3.y = 0f; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (!(sqrMagnitude < minSepSqr)) { float num3 = Vector3.Dot(((Vector3)(ref val3)).normalized, forward); if (!(num3 >= num)) { num = num3; num2 = sqrMagnitude; val = val2; } } } if ((Object)(object)val != (Object)null && num < -0.05f && num2 >= minSepSqr) { Collider componentInChildren = ((Component)val).GetComponentInChildren<Collider>(); Vector3 val4; if (!((Object)(object)componentInChildren != (Object)null)) { val4 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val4 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val4; ModLog.Info("Contest teleport: reverse track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, from); } } } catch (Exception ex) { ModLog.Debug("GetBackwardOnTrack failed: " + ex.Message); } return OffsetFarBehind(from, forward); } private static Vector3? GetFarthestRaceTrackPosition(Vector3 avoidNear, float minSepSqr) { //IL_004f: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType<ArenaRaceTrackPiece>(); if (array == null || array.Length == 0) { return null; } ArenaRaceTrackPiece val = null; float num = -1f; ArenaRaceTrackPiece[] array2 = array; foreach (ArenaRaceTrackPiece val2 in array2) { if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled) { float num2 = HorizontalSqr(((Component)val2).transform.position, avoidNear); if (!(num2 <= num)) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null || num < minSepSqr) { return null; } Collider componentInChildren = ((Component)val).GetComponentInChildren<Collider>(); Vector3 val3; if (!((Object)(object)componentInChildren != (Object)null)) { val3 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val3 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val3; ModLog.Info("Contest teleport: farthest track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, avoidNear); } catch (Exception ex) { ModLog.Debug("GetFarthestRaceTrackPosition failed: " + ex.Message); return null; } } private static Vector3? GetRandomRaceTrackPosition(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_0105: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType<ArenaRaceTrackPiece>(); if (array == null || array.Length == 0) { return null; } List<ArenaRaceTrackPiece> list = array.Where((ArenaRaceTrackPiece p) => (Object)(object)p != (Object)null && ((Behaviour)p).isActiveAndEnabled).ToList(); if (list.Count == 0) { return null; } List<ArenaRaceTrackPiece> list2 = list.Where((ArenaRaceTrackPiece p) => HorizontalSqr(((Component)p).transform.position, avoidNear) > 64f).ToList(); List<ArenaRaceTrackPiece> list3 = ((list2.Count > 0) ? list2 : list); ArenaRaceTrackPiece val = list3[Random.Range(0, list3.Count)]; Collider componentInChildren = ((Component)val).GetComponentInChildren<Collider>(); Vector3 val2; if (!((Object)(object)componentInChildren != (Object)null)) { val2 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val2 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val2; ModLog.Info("Contest teleport: driving track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, avoidNear); } catch (Exception ex) { ModLog.Debug("GetRandomRaceTrackPosition failed: " + ex.Message); return null; } } private static List<SpawnPoint> FindSpawnPoints() { SpawnPoint[] array = null; try { array = Object.FindObjectsOfType<SpawnPoint>(true); } catch { array = Object.FindObjectsOfType<SpawnPoint>(); } if (array != null) { return array.Where((SpawnPoint p) => (Object)(object)p != (Object)null).ToList(); } return new List<SpawnPoint>(); } private static Vector3 GetArenaCenter(Arena arena) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)arena.crownTransform != (Object)null) { return arena.crownTransform.position; } if ((Object)(object)arena.floorDoorTransform != (Object)null) { return arena.floorDoorTransform.position; } return ((Component)arena).transform.position; } private static bool IsBeforeCrownContestStart(Arena arena) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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: Invalid comparison between Unknown and I4 try { if (typeof(Arena).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(arena) is States val) { if ((int)val == 0 || (int)val == 5) { return true; } return false; } } catch { } return true; } } internal static class CartHelper { public static PhysGrabCart[] GetAllCarts() { return (from c in Object.FindObjectsOfType<PhysGrabCart>() where (Object)(object)c != (Object)null && ((Behaviour)c).isActiveAndEnabled select c).ToArray(); } public static List<PhysGrabObject> GetCartItemObjects(PhysGrabCart cart) { if (cart?.itemsInCart == null || cart.itemsInCart.Count == 0) { return new List<PhysGrabObject>(); } return cart.itemsInCart.Where((PhysGrabObject o) => (Object)(object)o != (Object)null).ToList(); } public static bool TeleportCart(PhysGrabCart cart, Vector3 targetPosition) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart == (Object)null) { return false; } Rigidbody rb = cart.rb; if ((Object)(object)rb == (Object)null) { return false; } float cartHeight = GetCartHeight(cart); Vector3 val = targetPosition + Vector3.up * cartHeight; Vector3 position = rb.position; rb.position = val; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; TeleportItemsInCart(cart, val, position); return true; } public static void TeleportItemsInCart(PhysGrabCart cart, Vector3 newPos, Vector3 oldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) Vector3 val = newPos - oldPos; foreach (PhysGrabObject cartItemObject in GetCartItemObjects(cart)) { try { cartItemObject.Teleport(((Component)cartItemObject).transform.position + val, ((Component)cartItemObject).transform.rotation); } catch (Exception ex) { ModLog.Debug("Cart item teleport failed: " + ex.Message); } } } public static void ShakeItemsInAllCarts(float minForce, float maxForce, float minDelay, float maxDelay) { PhysGrabCart[] allCarts = GetAllCarts(); if (allCarts.Length != 0) { EffectTimerHost.Instance.RunRoutine(ShakeAllCartsRoutine(allCarts, minForce, maxForce, minDelay, maxDelay)); } } public static bool TeleportAllCarts(bool toStart) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) PhysGrabCart[] allCarts = GetAllCarts(); if (allCarts.Length == 0) { return false; } LevelPoint lastPoint = null; bool result = false; PhysGrabCart[] array = allCarts; foreach (PhysGrabCart cart in array) { Vector3? val = (toStart ? GetNextStartRoomPoint(ref lastPoint) : GetNextRandomMapPoint(ref lastPoint, excludePlayerRooms: true)); if (val.HasValue && TeleportCart(cart, val.Value)) { result = true; } } return result; } private static IEnumerator ShakeAllCartsRoutine(PhysGrabCart[] carts, float minForce, float maxForce, float minDelay, float maxDelay) { float num = Mathf.Max(0f, Mathf.Min(minDelay, maxDelay)); float num2 = Mathf.Max(num, Mathf.Max(minDelay, maxDelay)); if (num2 > 0.001f) { yield return (object)new WaitForSeconds(Random.Range(num, num2)); } else { yield return null; } foreach (PhysGrabCart val in carts) { if ((Object)(object)val == (Object)null) { continue; } foreach (PhysGrabObject cartItemObject in GetCartItemObjects(val)) { Rigidbody rb = cartItemObject.rb; if (!((Object)(object)rb == (Object)null)) { rb.isKinematic = false; rb.WakeUp(); float num3 = Random.Range(minForce, maxForce); rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; rb.AddForce(Vector3.up * num3, (ForceMode)1); CartItemScatterBehavior cartItemScatterBehavior = ((Component)cartItemObject).gameObject.GetComponent<CartItemScatterBehavior>() ?? ((Component)cartItemObject).gameObject.AddComponent<CartItemScatterBehavior>(); cartItemScatterBehavior.Begin(); } } } } private static float GetCartHeight(PhysGrabCart cart) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Collider componentInParent = ((Component)cart).GetComponentInParent<Collider>(); if ((Object)(object)componentInParent == (Object)null) { return 1f; } Bounds bounds = componentInParent.bounds; return ((Bounds)(ref bounds)).size.y; } private static Vector3? GetNextStartRoomPoint(ref LevelPoint? lastPoint) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { List<LevelPoint> list = SemiFunc.LevelPointsGetInStartRoom(); if (list == null || list.Count == 0) { return GetPlayerSpawnPoint(); } lastPoint = PickNextPoint(list, lastPoint); LevelPoint? obj = lastPoint; return (obj != null) ? new Vector3?(((Component)obj).transform.position) : ((Vector3?)null); } catch (Exception ex) { ModLog.Debug("GetNextStartRoomPoint failed: " + ex.Message); return GetPlayerSpawnPoint(); } } private static Vector3? GetNextRandomMapPoint(ref LevelPoint? lastPoint, bool excludePlayerRooms) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) try { List<LevelPoint> list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { return null; } if (excludePlayerRooms) { List<LevelPoint> playerRooms = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List<LevelPoint>(); list = list.Where((LevelPoint p) => (Object)(object)p != (Object)null && !playerRooms.Contains(p)).ToList(); } if (list.Count == 0) { return null; } lastPoint = PickNextPoint(list, lastPoint); LevelPoint? obj = lastPoint; return (obj != null) ? new Vector3?(((Component)obj).transform.position) : ((Vector3?)null); } catch (Exception ex) { ModLog.Debug("GetNextRandomMapPoint failed: " + ex.Message); return null; } } private static LevelPoint PickNextPoint(IReadOnlyList<LevelPoint> points, LevelPoint? lastPoint) { if (points.Count == 1) { return points[0]; } int num = 0; LevelPoint val; do { val = points[Random.Range(0, points.Count)]; num++; } while ((Object)(object)val == (Object)(object)lastPoint && num < 8); return val; } private static Vector3? GetPlayerSpawnPoint() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) SpawnPoint[] array = Object.FindObjectsOfType<SpawnPoint>(); if (array == null || array.Length == 0) { return null; } return ((Component)array[Random.Range(0, array.Length)]).transform.position; } public static Vector3? GetRandomPlayerSpawnPoint(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = (from p in Object.FindObjectsOfType<SpawnPoint>() where (Object)(object)p != (Object)null select ((Component)p).transform.position).ToList(); if (list.Count == 0) { return SpawnHelper.TryGetStartRoomLevelPoint(0); } List<Vector3> list2 = list.OrderByDescending(delegate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = pos - avoidNear; return ((Vector3)(ref val)).sqrMagnitude; }).ToList(); return list2[Random.Range(0, list2.Count)]; } } internal sealed class CartItemScatterBehavior : MonoBehaviour { private Rigidbody? _rb; private bool _airborne; private float _airTime; private bool _ceilingHitThisArc; private float _cooldown; public void Begin() { _rb = ((Component)this).GetComponentInChildren<Rigidbody>(); } private void FixedUpdate() { if ((Object)(object)_rb == (Object)null || ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } _cooldown -= Time.fixedDeltaTime; CheckCeilingHit(); if (!IsGrounded()) { _airborne = true; _airTime += Time.fixedDeltaTime; return; } if (_airborne && _airTime > 0.12f) { ApplyImpact(heavy: false); if (ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } } _airborne = false; _airTime = 0f; _ceilingHitThisArc = false; } private void CheckCeilingHit() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rb == (Object)null) && !_ceilingHitThisArc && !(_rb.velocity.y < 0.8f)) { Vector3 val = ((Component)this).transform.position + Vector3.up * 0.15f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.up, ref val2, 1.4f, -5, (QueryTriggerInteraction)1) && !(((RaycastHit)(ref val2)).normal.y > -0.2f) && !(_cooldown > 0f)) { ApplyImpact(heavy: true); _ceilingHitThisArc = true; } } } private void ApplyImpact(bool heavy) { if (!(_cooldown > 0f)) { _cooldown = 0.18f; ValuableDamageHelper.ApplyImpactDamage(((Component)this).gameObject, 0.22f, heavy); } } private bool IsGrounded() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)this).transform.position + Vector3.up * 0.1f; return Physics.Raycast(val, Vector3.down, 0.35f, -5, (QueryTriggerInteraction)1); } } internal sealed class ChompBookHuntBehavior : MonoBehaviour { private ChompBookTrap? _trap; private Transform? _player; private float _duration = 45f; private float _elapsed; private float _attackTimer = 0.15f; public void Configure(ChompBookTrap trap, float durationSeconds = 45f) { _trap = trap; _duration = Mathf.Max(12f, durationSeconds); PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _player = ((localPlayer != null) ? ((Component)localPlayer).transform : null); ForceTrapOn(); RefreshTarget(); TryAttack(); } private void FixedUpdate() { if ((Object)(object)_trap == (Object)null || ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { try { _trap.TrapStop(); } catch { } Object.Destroy((Object)(object)this); return; } ForceTrapOn(); RefreshTarget(); _attackTimer -= Time.fixedDeltaTime; if (_attackTimer <= 0f) { _attackTimer = 1.05f; TryAttack(); } } private void ForceTrapOn() { if (!((Object)(object)_trap == (Object)null)) { ((Trap)_trap).isLocal = true; ((Trap)_trap).trapStart = true; if (_trap.biteAmount < 8) { _trap.biteAmount = 12; } try { _trap.TrapActivate(); } catch { TryInvoke(_trap, "TrapActivate"); } Animator component = ((Component)_trap).GetComponent<Animator>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; } } } private void RefreshTarget() { if ((Object)(object)_trap == (Object)null) { return; } if ((Object)(object)_player == (Object)null) { PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _player = ((localPlayer != null) ? ((Component)localPlayer).transform : null); } if ((Object)(object)_player == (Object)null) { return; } try { typeof(ChompBookTrap).GetField("targetTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(_trap, _player); } catch { } } private void TryAttack() { if ((Object)(object)_trap == (Object)null) { return; } try { _trap.Attack(); } catch (Exception ex) { ModLog.Debug("Chomp Book Attack: " + ex.Message); } } private static void TryInvoke(object target, string methodName) { tr