using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using SpectateRace.Config; using SpectateRace.Core; using TMPro; using UnityEngine; using UnityEngine.TextCore.LowLevel; 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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Kai")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+bc2ce350dc1a821cbdd397a7f00b5ea8dcdf6a3e")] [assembly: AssemblyProduct("SpectateRace")] [assembly: AssemblyTitle("SpectateRace")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SpectateRace { [BepInPlugin("Kai.SpectateRace", "SpectateRace", "1.4")] public class SpectateRace : BaseUnityPlugin { internal static SpectateRace Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); RaceWorldLabelConfig.Bind(((BaseUnityPlugin)this).Config); SpectateRaceViewConfig.Bind(((BaseUnityPlugin)this).Config); RaceQuickStartConfig.Bind(((BaseUnityPlugin)this).Config); if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent())) { ((Component)this).gameObject.AddComponent(); Logger.LogInfo((object)"[WorldLabel] Manager attached to plugin object."); } if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent())) { ((Component)this).gameObject.AddComponent(); Logger.LogInfo((object)"[ViewTweaks] Manager attached to plugin object."); } if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent())) { ((Component)this).gameObject.AddComponent(); Logger.LogInfo((object)"[RaceQuickStart] Controller attached to plugin object."); } Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } private void Update() { } } } namespace SpectateRace.Patchs { [HarmonyPatch(typeof(ArenaRaceTimerUI), "OnPlacementsUpdated")] internal static class Patch_ArenaRaceTimerUI_OnPlacementsUpdated { private static void Postfix(List _newOrder) { RacePlacementCache.Set(_newOrder); SpectateRaceNameUpdater.RefreshSpectateName(); } } [HarmonyPatch(typeof(ArenaRaceTimerUI), "Update")] internal static class Patch_ArenaRaceTimerUI_Update_ShowPlacementsWhileSpectating { private static void Postfix(ArenaRaceTimerUI __instance) { if (!Object.op_Implicit((Object)(object)__instance) || !SemiFunc.RunIsArena() || !SemiFunc.IsSpectating() || !Object.op_Implicit((Object)(object)ArenaRace.instance)) { return; } TextMeshProUGUI allPlacementsText = __instance.allPlacementsText; if (Object.op_Implicit((Object)(object)allPlacementsText)) { ((Component)__instance).gameObject.SetActive(true); if (Object.op_Implicit((Object)(object)__instance.secondsText)) { ((Behaviour)__instance.secondsText).enabled = false; } if (Object.op_Implicit((Object)(object)__instance.hundredthsText)) { ((Behaviour)__instance.hundredthsText).enabled = false; } if (Object.op_Implicit((Object)(object)__instance.clearedText)) { ((Behaviour)__instance.clearedText).enabled = false; } if (Object.op_Implicit((Object)(object)__instance.progressText)) { ((Behaviour)__instance.progressText).enabled = false; } if (Object.op_Implicit((Object)(object)__instance.placeText)) { ((Behaviour)__instance.placeText).enabled = false; } if (Object.op_Implicit((Object)(object)__instance.trackPieceText)) { ((Behaviour)__instance.trackPieceText).enabled = false; } ((Behaviour)allPlacementsText).enabled = true; ((Component)allPlacementsText).gameObject.SetActive(true); } } } [HarmonyPatch(typeof(MenuPlayerHead), "Update")] internal static class Patch_MenuPlayerHead_SpectateRace { private static bool Prefix(MenuPlayerHead __instance) { if (!SpectateRaceViewTweaks.ShouldHidePlayerMenuHead) { return true; } if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).gameObject.activeSelf) { ((Component)__instance).gameObject.SetActive(false); } return false; } } [HarmonyPatch(typeof(MenuPlayerListed), "Update")] internal static class Patch_MenuPlayerListed_SpectateRace { private static bool Prefix(MenuPlayerListed __instance) { if (!SpectateRaceViewTweaks.ShouldHideSpectatePlayerList) { return true; } if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).gameObject.activeSelf) { ((Component)__instance).gameObject.SetActive(false); } return false; } } [HarmonyPatch(typeof(SpectateCamera), "PlayerSwitch")] internal static class Patch_SpectateCamera_PlayerSwitch { private static void Postfix() { SpectateRaceNameUpdater.RefreshSpectateName(); } } [HarmonyPatch(typeof(SpectateCamera), "StateNormal")] internal static class Patch_SpectateCamera_StateNormal_MaxDistance { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private IEnumerator <>7__wrap1; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (current.opcode == OpCodes.Ldc_R4 && current.operand is float num && num == 6f) { <>2__current = CodeInstruction.Call(typeof(Patch_SpectateCamera_StateNormal_MaxDistance), "GetMaxDistance", (Type[])null, (Type[])null); <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__0 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__0(0); } d__.instructions = <>3__instructions; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [IteratorStateMachine(typeof(d__0))] private static IEnumerable Transpiler(IEnumerable instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2) { <>3__instructions = instructions }; } private static float GetMaxDistance() { if (SpectateRaceViewConfig.SpectateCameraMaxDistance == null) { return 6f; } return SpectateRaceViewConfig.SpectateCameraMaxDistance.Value; } } } namespace SpectateRace.Core { internal static class RacePlaceFormatter { public static string GetOrdinal(int place) { if (place <= 0) { return string.Empty; } int num = place % 100; if (num >= 11 && num <= 13) { return place + "th"; } return (place % 10) switch { 1 => place + "st", 2 => place + "nd", 3 => place + "rd", _ => place + "th", }; } public static string GetPlaceColor(int place) { return place switch { 1 => "#FFD700", 2 => "#9AD7FF", 3 => "#D0822A", _ => "#B8B8B8", }; } public static string GetColoredOrdinal(int place) { string ordinal = GetOrdinal(place); if (string.IsNullOrEmpty(ordinal)) { return string.Empty; } string placeColor = GetPlaceColor(place); return "" + ordinal + ""; } public static string BuildColoredName(int place, string playerName) { string coloredOrdinal = GetColoredOrdinal(place); string text = EscapeRichText(playerName); if (string.IsNullOrEmpty(coloredOrdinal)) { return "" + text + ""; } return coloredOrdinal + " " + text + ""; } private static string EscapeRichText(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } return text.Replace("&", "&").Replace("<", "<").Replace(">", ">"); } } internal static class RacePlacementCache { private static readonly List Placements = new List(); public static void Set(List players) { Placements.Clear(); if (players == null) { return; } foreach (PlayerAvatar player in players) { if ((Object)(object)player != (Object)null && !player.isDisabled) { Placements.Add(player); } } } public static int GetPlace(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return -1; } for (int i = 0; i < Placements.Count; i++) { if ((Object)(object)Placements[i] == (Object)(object)player) { return i + 1; } } return -1; } public static List GetPlacementsSnapshot() { return new List(Placements); } public static void Clear() { Placements.Clear(); } } internal sealed class RaceQuickStartController : MonoBehaviour { private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(RaceQuickStartConfig.RaceQuickStartKey.Value) && SemiFunc.NoTextInputsActive()) { StartArenaRace(); } } private static void StartArenaRace() { RunManager instance = RunManager.instance; if ((Object)(object)instance == (Object)null) { SpectateRace.Logger.LogWarning((object)"[RaceQuickStart] RunManager not found."); return; } if (instance.restarting) { SpectateRace.Logger.LogInfo((object)"[RaceQuickStart] Scene is already restarting."); return; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { SpectateRace.Logger.LogInfo((object)"[RaceQuickStart] Only host or singleplayer can change level."); return; } if (instance.levelArena == null || instance.levelArena.Count == 0) { SpectateRace.Logger.LogWarning((object)"[RaceQuickStart] Arena level list is empty."); return; } EnsureRunInitializedFromMainMenu(instance); Level val = PickArenaRaceLevel(instance); if ((Object)(object)val == (Object)null) { SpectateRace.Logger.LogWarning((object)"[RaceQuickStart] Arena Race level not found."); return; } ChangeToLevelDirect(instance, val); SpectateRace.Logger.LogInfo((object)("[RaceQuickStart] Changing level: " + ((Object)val).name)); } private static Level PickArenaRaceLevel(RunManager run) { if (run.levelArena == null || run.levelArena.Count == 0) { return null; } foreach (Level item in run.levelArena) { if (!((Object)(object)item == (Object)null) && string.Equals(((Object)item).name, "Arena Race", StringComparison.OrdinalIgnoreCase)) { return item; } } foreach (Level item2 in run.levelArena) { if (!((Object)(object)item2 == (Object)null) && ((Object)item2).name.IndexOf("Race", StringComparison.OrdinalIgnoreCase) >= 0) { return item2; } } return null; } private static void ChangeToLevelDirect(RunManager run, Level level) { run.gameOver = false; run.levelCurrent = level; if (GameManager.Multiplayer()) { run.runManagerPUN.photonView.RPC("UpdateLevelRPC", (RpcTarget)4, new object[3] { ((Object)level).name, run.levelsCompleted, false }); } run.UpdateSteamRichPresence(); if (SemiFunc.IsLevelShop(level)) { run.saveLevel = 1; } else if ((Object)(object)level == (Object)(object)run.levelLobby) { run.saveLevel = 2; } else { run.saveLevel = 0; } SemiFunc.StatSetSaveLevel(run.saveLevel); run.RestartScene(); SemiFunc.OnSceneSwitch(false, false); } private static void EnsureRunInitializedFromMainMenu(RunManager run) { if (!((Object)(object)run == (Object)null) && SemiFunc.IsMainMenu()) { if ((Object)(object)StatsManager.instance != (Object)null) { StatsManager.instance.ResetAllStats(); } run.levelsCompleted = 0; run.loadLevel = 0; run.runStarted = true; run.gameOver = false; } } } internal sealed class RaceWorldLabel : MonoBehaviour { private PlayerAvatar _player; private int _place; private Canvas _canvas; private RectTransform _root; private RectTransform _glowRect; private Image _glowImage; private Image _backgroundImage; private TextMeshProUGUI _text; private float _currentScale; public static RaceWorldLabel Create(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown GameObject val = new GameObject("SpectateRace.WorldLabel"); val.transform.SetParent(parent, false); RaceWorldLabel raceWorldLabel = val.AddComponent(); raceWorldLabel.Build(); return raceWorldLabel; } public void Bind(PlayerAvatar player, int place) { _player = player; _place = place; string playerName = player.playerName; string sampleText = RacePlaceFormatter.GetOrdinal(place) + " " + playerName; RaceWorldLabelFontResolver.Apply(_text, sampleText); ((TMP_Text)_text).text = RacePlaceFormatter.BuildColoredName(place, playerName); ApplyVisualStyle(place); } public void Tick(Camera cam) { //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_0021: 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) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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_0127: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_player)) { ((Component)this).gameObject.SetActive(false); return; } Vector3 targetPosition = GetTargetPosition(); Vector3 val = targetPosition - ((Component)cam).transform.position; if (RaceWorldLabelConfig.HideBehindCamera.Value) { float num = Vector3.Dot(((Component)cam).transform.forward, ((Vector3)(ref val)).normalized); if (num <= 0f) { ((Component)this).gameObject.SetActive(false); return; } } if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } ((Component)this).transform.position = targetPosition; ((Component)this).transform.rotation = Quaternion.LookRotation(((Component)this).transform.position - ((Component)cam).transform.position, ((Component)cam).transform.up); float distance = Vector3.Distance(((Component)cam).transform.position, targetPosition); float num2 = CalculateScale(distance); if (_currentScale <= 0f) { _currentScale = num2; } else { _currentScale = Mathf.Lerp(_currentScale, num2, Time.deltaTime * 8f); } ((Component)this).transform.localScale = Vector3.one * _currentScale; } private Vector3 GetTargetPosition() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) float value = RaceWorldLabelConfig.HeightOffset.Value; return ((Component)_player).transform.position + Vector3.up * value; } private float CalculateScale(float distance) { float value = RaceWorldLabelConfig.MinScaleDistance.Value; float value2 = RaceWorldLabelConfig.MaxScaleDistance.Value; float num = Mathf.InverseLerp(value, value2, distance); float value3 = RaceWorldLabelConfig.MinScale.Value; float value4 = RaceWorldLabelConfig.MaxScale.Value; return Mathf.Lerp(value3, value4, num); } private void Build() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) _canvas = ((Component)this).gameObject.AddComponent(); _canvas.renderMode = (RenderMode)2; _canvas.sortingOrder = 5000; _root = ((Component)this).gameObject.GetComponent(); _root.sizeDelta = new Vector2(360f, 64f); CreateGlow(); CreateBackground(); CreateText(); } private void CreateGlow() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0097: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Glow"); val.transform.SetParent(((Component)this).transform, false); _glowRect = val.AddComponent(); _glowRect.anchorMin = new Vector2(0.5f, 0.5f); _glowRect.anchorMax = new Vector2(0.5f, 0.5f); _glowRect.pivot = new Vector2(0.5f, 0.5f); _glowRect.anchoredPosition = Vector2.zero; _glowRect.sizeDelta = new Vector2(380f, 80f); _glowImage = val.AddComponent(); ((Graphic)_glowImage).raycastTarget = false; } private void CreateBackground() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Background"); val.transform.SetParent(((Component)this).transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = new Vector2(340f, 56f); _backgroundImage = val.AddComponent(); ((Graphic)_backgroundImage).raycastTarget = false; ((Graphic)_backgroundImage).color = new Color(0f, 0f, 0f, 0.65f); } private void CreateText() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0079: 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) GameObject val = new GameObject("Text"); val.transform.SetParent(((Component)this).transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = new Vector2(320f, 48f); _text = val.AddComponent(); ((Graphic)_text).raycastTarget = false; ((TMP_Text)_text).richText = true; ((TMP_Text)_text).alignment = (TextAlignmentOptions)514; ((TMP_Text)_text).fontSize = 30f; ((TMP_Text)_text).enableWordWrapping = false; ((TMP_Text)_text).overflowMode = (TextOverflowModes)0; ((TMP_Text)_text).outlineWidth = 0.18f; ((TMP_Text)_text).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220); } private void ApplyVisualStyle(int place) { //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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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) Color val = ParseColor(RacePlaceFormatter.GetPlaceColor(place)); ((Graphic)_glowImage).color = new Color(val.r, val.g, val.b, place switch { 1 => 0.28f, 2 => 0.2f, 3 => 0.24f, _ => 0.08f, }); RectTransform glowRect = _glowRect; glowRect.sizeDelta = (Vector2)(place switch { 1 => new Vector2(400f, 86f), 2 => new Vector2(380f, 78f), 3 => new Vector2(380f, 78f), _ => new Vector2(360f, 68f), }); } private static Color ParseColor(string htmlColor) { //IL_000c: 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) Color result = default(Color); if (ColorUtility.TryParseHtmlString(htmlColor, ref result)) { return result; } return Color.white; } } internal static class RaceWorldLabelFontResolver { private static TMP_FontAsset _cachedFont; private static TMP_FontAsset _cachedJapaneseFallback; private static bool _loggedFontInfo; public static void Apply(TextMeshProUGUI text, string sampleText = null) { if (Object.op_Implicit((Object)(object)text)) { TMP_FontAsset orCreateFont = GetOrCreateFont(); if (Object.op_Implicit((Object)(object)orCreateFont)) { ((TMP_Text)text).font = orCreateFont; } } } private static TMP_FontAsset GetOrCreateFont() { if (Object.op_Implicit((Object)(object)_cachedFont)) { return _cachedFont; } TMP_FontAsset defaultTmpFont = GetDefaultTmpFont(); if (!Object.op_Implicit((Object)(object)defaultTmpFont)) { Debug.LogWarning((object)"[SpectateRace] TMP default font was not found."); return null; } _cachedFont = Object.Instantiate(defaultTmpFont); ((Object)_cachedFont).name = "SpectateRace_LabelFont"; if (_cachedFont.fallbackFontAssetTable == null) { _cachedFont.fallbackFontAssetTable = new List(); } AddFallbacksFromBaseFont(defaultTmpFont, _cachedFont); AddFallbacksFromTmpSettings(_cachedFont); TMP_FontAsset japaneseFallback = GetJapaneseFallback(); if (Object.op_Implicit((Object)(object)japaneseFallback) && !_cachedFont.fallbackFontAssetTable.Contains(japaneseFallback)) { _cachedFont.fallbackFontAssetTable.Add(japaneseFallback); Debug.Log((object)("[SpectateRace] Japanese TMP fallback added: " + ((Object)japaneseFallback).name)); } else if (!Object.op_Implicit((Object)(object)japaneseFallback)) { Debug.LogWarning((object)"[SpectateRace] Japanese TMP fallback was not found. Japanese names may appear as tofu."); LogAvailableFontsOnce(); } return _cachedFont; } private static TMP_FontAsset GetDefaultTmpFont() { if (Object.op_Implicit((Object)(object)TMP_Settings.defaultFontAsset)) { return TMP_Settings.defaultFontAsset; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if (Object.op_Implicit((Object)(object)val) && ((Object)val).name.Contains("LiberationSans")) { return val; } } if (array.Length == 0) { return null; } return array[0]; } private static void AddFallbacksFromBaseFont(TMP_FontAsset source, TMP_FontAsset target) { if (!Object.op_Implicit((Object)(object)source) || source.fallbackFontAssetTable == null) { return; } foreach (TMP_FontAsset item in source.fallbackFontAssetTable) { if (Object.op_Implicit((Object)(object)item) && !target.fallbackFontAssetTable.Contains(item)) { target.fallbackFontAssetTable.Add(item); } } } private static void AddFallbacksFromTmpSettings(TMP_FontAsset target) { if (TMP_Settings.fallbackFontAssets == null) { return; } foreach (TMP_FontAsset fallbackFontAsset in TMP_Settings.fallbackFontAssets) { if (Object.op_Implicit((Object)(object)fallbackFontAsset) && !target.fallbackFontAssetTable.Contains(fallbackFontAsset)) { target.fallbackFontAssetTable.Add(fallbackFontAsset); } } } private static TMP_FontAsset GetJapaneseFallback() { if (Object.op_Implicit((Object)(object)_cachedJapaneseFallback)) { return _cachedJapaneseFallback; } _cachedJapaneseFallback = FindJapaneseFontAsset(); if (Object.op_Implicit((Object)(object)_cachedJapaneseFallback)) { return _cachedJapaneseFallback; } Debug.LogWarning((object)"[SpectateRace] Japanese TMP fallback was not found. Japanese names may appear as tofu."); LogAvailableFontsOnce(); return null; } private static TMP_FontAsset FindJapaneseFontAsset() { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if (Object.op_Implicit((Object)(object)val)) { string text = ((Object)val).name.ToLowerInvariant(); if ((text.Contains("japanese") || text.Contains("jp") || text.Contains("noto") || text.Contains("sourcehan") || text.Contains("mplus") || text.Contains("yugothic") || text.Contains("meiryo") || text.Contains("gothic")) && CanRenderJapanese(val)) { return val; } } } TMP_FontAsset[] array3 = array; foreach (TMP_FontAsset val2 in array3) { if (Object.op_Implicit((Object)(object)val2) && CanRenderJapanese(val2)) { return val2; } } return null; } private static TMP_FontAsset CreateJapaneseOsFontAsset() { string[] array = new string[6] { "Yu Gothic UI", "Yu Gothic", "Meiryo", "MS Gothic", "Noto Sans CJK JP", "Noto Sans JP" }; Font val = Font.CreateDynamicFontFromOSFont(array, 90); if (!Object.op_Implicit((Object)(object)val)) { Debug.LogWarning((object)"[SpectateRace] Failed to create Japanese OS font."); return null; } TMP_FontAsset val2 = TMP_FontAsset.CreateFontAsset(val, 90, 9, (GlyphRenderMode)4165, 1024, 1024, (AtlasPopulationMode)1, true); if (!Object.op_Implicit((Object)(object)val2)) { Debug.LogWarning((object)"[SpectateRace] Failed to create TMP font asset from Japanese OS font."); return null; } ((Object)val2).name = "SpectateRace_Japanese_OSFont_Fallback"; val2.atlasPopulationMode = (AtlasPopulationMode)1; val2.isMultiAtlasTexturesEnabled = true; Debug.Log((object)("[SpectateRace] Created Japanese OS font fallback: " + ((Object)val).name)); return val2; } private static bool CanRenderJapanese(TMP_FontAsset font) { return CanRender(font, "日本語ハヒフヘホ"); } private static bool CanRender(TMP_FontAsset font, string text) { if (!Object.op_Implicit((Object)(object)font) || string.IsNullOrEmpty(text)) { return false; } foreach (char c in text) { if (!char.IsWhiteSpace(c) && !font.HasCharacter(c, true, true)) { return false; } } return true; } private static void LogAvailableFontsOnce() { if (_loggedFontInfo) { return; } _loggedFontInfo = true; TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); Debug.Log((object)("[SpectateRace] Available TMP fonts: " + array.Length)); TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if (Object.op_Implicit((Object)(object)val)) { Debug.Log((object)("[SpectateRace] TMP font: " + ((Object)val).name)); } } } } internal sealed class RaceWorldLabelManager : MonoBehaviour { private readonly Dictionary _labels = new Dictionary(); private RaceWorldLabelMode _mode; private float _refreshTimer; private void Awake() { _mode = RaceWorldLabelConfig.DefaultMode.Value; } private void Update() { HandleToggle(); if (!ShouldRun()) { ClearLabels(); return; } _refreshTimer -= Time.deltaTime; if (_refreshTimer <= 0f) { _refreshTimer = 0.1f; RefreshLabels(); } UpdateLabels(); } private void HandleToggle() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(RaceWorldLabelConfig.ToggleKey.Value)) { _mode = _mode switch { RaceWorldLabelMode.Off => RaceWorldLabelMode.Top3, RaceWorldLabelMode.Top3 => RaceWorldLabelMode.All, _ => RaceWorldLabelMode.Off, }; SpectateRace.Logger.LogInfo((object)$"[WorldLabels] Mode: {_mode}"); } } private bool ShouldRun() { if (_mode == RaceWorldLabelMode.Off) { return false; } if (!SemiFunc.RunIsArena()) { return false; } if (!SemiFunc.IsSpectating()) { return false; } if (!Object.op_Implicit((Object)(object)ArenaRace.instance)) { return false; } return true; } private void RefreshLabels() { List placementsSnapshot = RacePlacementCache.GetPlacementsSnapshot(); HashSet hashSet = new HashSet(); for (int i = 0; i < placementsSnapshot.Count; i++) { PlayerAvatar val = placementsSnapshot[i]; if (!Object.op_Implicit((Object)(object)val) || val.isDisabled) { continue; } int num = i + 1; if (_mode != RaceWorldLabelMode.Top3 || num <= 3) { hashSet.Add(val); if (!_labels.TryGetValue(val, out RaceWorldLabel value) || !Object.op_Implicit((Object)(object)value)) { value = RaceWorldLabel.Create(((Component)this).transform); _labels[val] = value; } value.Bind(val, num); } } RemoveInactiveLabels(hashSet); } private void UpdateLabels() { Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } foreach (RaceWorldLabel value in _labels.Values) { if (Object.op_Implicit((Object)(object)value)) { value.Tick(main); } } } private void RemoveInactiveLabels(HashSet activePlayers) { List list = new List(); foreach (KeyValuePair label in _labels) { PlayerAvatar key = label.Key; RaceWorldLabel value = label.Value; if (!Object.op_Implicit((Object)(object)key) || !activePlayers.Contains(key)) { if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)((Component)value).gameObject); } list.Add(key); } } foreach (PlayerAvatar item in list) { _labels.Remove(item); } } private void ClearLabels() { if (_labels.Count <= 0) { return; } foreach (RaceWorldLabel value in _labels.Values) { if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)((Component)value).gameObject); } } _labels.Clear(); } } internal enum RaceWorldLabelMode { Off, Top3, All } internal static class SpectateRaceNameUpdater { private static string _lastDisplayName; public static void RefreshSpectateName() { if (!SemiFunc.RunIsArena() || !SemiFunc.IsSpectating() || !Object.op_Implicit((Object)(object)ArenaRace.instance) || !Object.op_Implicit((Object)(object)SpectateCamera.instance)) { return; } PlayerAvatar player = SpectateCamera.instance.player; if (!Object.op_Implicit((Object)(object)player)) { return; } int place = RacePlacementCache.GetPlace(player); if (place > 0) { string coloredOrdinal = RacePlaceFormatter.GetColoredOrdinal(place); string text = coloredOrdinal + " " + player.playerName; if (!(_lastDisplayName == text)) { _lastDisplayName = text; SemiFunc.HUDSpectateSetName(text); } } } public static void ResetCache() { _lastDisplayName = null; } } internal sealed class SpectateRaceViewTweaks : MonoBehaviour { private const float PhotoModeFarClipPlane = 500f; private const float PhotoModeShadowDistance = 300f; private const float PhotoModeLodBias = 3f; private const int PhotoModeMaximumLodLevel = 0; private bool _active; private bool _savedFog; private bool _fogSaved; private Color _savedAmbientLight; private bool _ambientLightSaved; private float _savedFarClipPlane; private bool _farClipSaved; private float _savedShadowDistance; private bool _shadowDistanceSaved; private float _savedLodBias; private bool _lodBiasSaved; private int _savedMaximumLodLevel; private bool _maximumLodLevelSaved; private MenuSpectateList _menuSpectateList; private readonly List _hiddenPlayerMenuHeads = new List(); private readonly List _hiddenSpectateHeadUis = new List(); private readonly List _hiddenSpectateListObjects = new List(); private readonly List _hiddenMenuPlayerListedObjects = new List(); private float _uiRefreshTimer; internal static SpectateRaceViewTweaks Instance { get; private set; } internal static bool ShouldHidePlayerMenuHead { get { if ((Object)(object)Instance != (Object)null && Instance._active && !AllPlayersDead()) { return SpectateRaceViewConfig.HidePlayerMenuHead.Value; } return false; } } internal static bool ShouldHideSpectatePlayerList { get { if ((Object)(object)Instance != (Object)null && Instance._active && !AllPlayersDead()) { return SpectateRaceViewConfig.HideSpectatePlayerList.Value; } return false; } } private void Awake() { Instance = this; } private void OnDestroy() { RestoreAll(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void OnDisable() { RestoreAll(); } private void Update() { HandleInput(); bool flag = ShouldRun(); if (flag && !_active) { Enable(); } else if (!flag && _active) { Disable(); return; } if (_active) { HideUiTick(); } } private void LateUpdate() { if (_active && ShouldRun()) { ApplyViewTweaks(); } } private void HandleInput() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!IsArenaRaceSpectateContext() || (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))) { return; } float y = Input.mouseScrollDelta.y; if (Mathf.Abs(y) <= 0.001f) { return; } float num = Mathf.Clamp(SpectateRaceViewConfig.NightVisionStrength.Value, 0f, 100f); float num2 = Mathf.Max(1f, SpectateRaceViewConfig.NightVisionWheelStep.Value); float num3 = Mathf.Clamp(num + y * num2, 0f, 100f); if (!Mathf.Approximately(num, num3)) { SpectateRaceViewConfig.NightVisionStrength.Value = num3; if (_active) { ApplyNightVisionOnly(); } SpectateRace.Logger.LogInfo((object)$"[ViewTweaks] NightVision: {num3:0}"); } } private static bool IsArenaRaceSpectateContext() { if (!SpectateRaceViewConfig.EnableViewTweaks.Value) { return false; } if (!SemiFunc.RunIsArena()) { return false; } if (!SemiFunc.IsSpectating()) { return false; } if (!Object.op_Implicit((Object)(object)ArenaRace.instance)) { return false; } if (AllPlayersDead()) { return false; } return true; } private static bool ShouldRun() { if ((Object)(object)Instance == (Object)null) { return false; } return IsArenaRaceSpectateContext(); } internal static bool AllPlayersDead() { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return false; } if (GameDirector.instance.PlayerList.Count == 0) { return false; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player != (Object)null && !player.isDisabled) { return false; } } return true; } private void Enable() { SaveCurrentValues(); CacheUiReferences(); _active = true; ApplyViewTweaks(); HideUi(includeInactive: true); } private void Disable() { RestoreAll(); _active = false; } private void SaveCurrentValues() { //IL_0074: 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) _savedFog = RenderSettings.fog; _fogSaved = true; Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { _savedFarClipPlane = mainCamera.farClipPlane; _farClipSaved = true; } else { _farClipSaved = false; } _savedShadowDistance = QualitySettings.shadowDistance; _shadowDistanceSaved = true; _savedLodBias = QualitySettings.lodBias; _lodBiasSaved = true; _savedMaximumLodLevel = QualitySettings.maximumLODLevel; _maximumLodLevelSaved = true; _savedAmbientLight = RenderSettings.ambientLight; _ambientLightSaved = true; } private void ApplyViewTweaks() { ApplyPhotoModeValues(); ApplyNightVision(); } private void ApplyNightVisionOnly() { ApplyNightVision(); } private void ApplyPhotoModeValues() { if (SpectateRaceViewConfig.DisableFog.Value) { RenderSettings.fog = false; } Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { mainCamera.farClipPlane = 500f; } QualitySettings.shadowDistance = 300f; QualitySettings.lodBias = Mathf.Max(QualitySettings.lodBias, 3f); QualitySettings.maximumLODLevel = 0; } private void ApplyNightVision() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_002b: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(SpectateRaceViewConfig.NightVisionStrength.Value, 0f, 100f); if (num <= 0.001f) { if (_ambientLightSaved) { RenderSettings.ambientLight = _savedAmbientLight; } } else { float num2 = Mathf.Clamp01(num / 100f); Color ambientLight = RenderSettings.ambientLight; Color ambientLight2 = Color.Lerp(ambientLight, Color.white * 2f, num2); RenderSettings.ambientLight = ambientLight2; } } private void HideUiTick() { _uiRefreshTimer -= Time.deltaTime; if (!(_uiRefreshTimer > 0f)) { _uiRefreshTimer = 0.25f; HideUi(includeInactive: false); } } private void HideUi(bool includeInactive) { CacheUiReferences(); if (SpectateRaceViewConfig.HidePlayerMenuHead.Value) { HidePlayerMenuHeads(includeInactive); } if (SpectateRaceViewConfig.HideSpectateHeadUI.Value) { HideSpectateHeadUis(includeInactive); } if (SpectateRaceViewConfig.HideSpectatePlayerList.Value) { HideSpectatePlayerList(); } } private void CacheUiReferences() { if (!Object.op_Implicit((Object)(object)_menuSpectateList)) { _menuSpectateList = Object.FindObjectOfType(true); } } private void HidePlayerMenuHeads(bool includeInactive) { MenuPlayerHead[] array = Object.FindObjectsOfType(includeInactive); MenuPlayerHead[] array2 = array; foreach (MenuPlayerHead val in array2) { if (Object.op_Implicit((Object)(object)val)) { HideGameObject(((Component)val).gameObject, _hiddenPlayerMenuHeads); } } } private void HideSpectateHeadUis(bool includeInactive) { SpectateHeadUI[] array = Object.FindObjectsOfType(includeInactive); SpectateHeadUI[] array2 = array; foreach (SpectateHeadUI val in array2) { if (Object.op_Implicit((Object)(object)val)) { HideGameObject(((Component)val).gameObject, _hiddenSpectateHeadUis); } } } private void HideSpectatePlayerList() { if (Object.op_Implicit((Object)(object)_menuSpectateList)) { ((SemiUI)_menuSpectateList).Hide(); HideMenuPlayerListedChildren(); HideGameObject(((Component)_menuSpectateList).gameObject, _hiddenSpectateListObjects); GameObject val = FindSpectateListContainer(((Component)_menuSpectateList).transform); if (Object.op_Implicit((Object)(object)val)) { HideGameObject(val, _hiddenSpectateListObjects); } } } private static GameObject FindSpectateListContainer(Transform start) { if (!Object.op_Implicit((Object)(object)start)) { return null; } Transform val = start; Transform val2 = start; while (Object.op_Implicit((Object)(object)val.parent)) { Transform parent = val.parent; if (Object.op_Implicit((Object)(object)((Component)parent).GetComponent())) { break; } string text = ((Object)((Component)parent).gameObject).name.ToLowerInvariant(); if (!text.Contains("spectate") && !text.Contains("player") && !text.Contains("list")) { break; } val2 = parent; val = parent; } if (!Object.op_Implicit((Object)(object)val2)) { return null; } return ((Component)val2).gameObject; } private void HideMenuPlayerListedChildren() { if (!Object.op_Implicit((Object)(object)_menuSpectateList)) { return; } for (int i = 0; i < _menuSpectateList.listObjects.Count; i++) { GameObject val = _menuSpectateList.listObjects[i]; if (Object.op_Implicit((Object)(object)val)) { HideGameObject(val, _hiddenMenuPlayerListedObjects); } } } private static void HideGameObject(GameObject go, List restoreList) { if (Object.op_Implicit((Object)(object)go) && go.activeSelf) { go.SetActive(false); if (!restoreList.Contains(go)) { restoreList.Add(go); } } } private void RestoreAll() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (_fogSaved) { RenderSettings.fog = _savedFog; } Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null && _farClipSaved) { mainCamera.farClipPlane = _savedFarClipPlane; } if (_shadowDistanceSaved) { QualitySettings.shadowDistance = _savedShadowDistance; } if (_lodBiasSaved) { QualitySettings.lodBias = _savedLodBias; } if (_maximumLodLevelSaved) { QualitySettings.maximumLODLevel = _savedMaximumLodLevel; } if (_ambientLightSaved) { RenderSettings.ambientLight = _savedAmbientLight; } RestorePlayerMenuHeads(); RestoreSpectateHeadUis(); RestoreSpectatePlayerList(); ClearSavedFlags(); } private void RestorePlayerMenuHeads() { RestoreGameObjects(_hiddenPlayerMenuHeads); } private void RestoreSpectateHeadUis() { RestoreGameObjects(_hiddenSpectateHeadUis); } private void RestoreSpectatePlayerList() { RestoreGameObjects(_hiddenSpectateListObjects); RestoreGameObjects(_hiddenMenuPlayerListedObjects); if (Object.op_Implicit((Object)(object)_menuSpectateList)) { ((Behaviour)_menuSpectateList).enabled = true; } } private static void RestoreGameObjects(List objects) { for (int i = 0; i < objects.Count; i++) { GameObject val = objects[i]; if (Object.op_Implicit((Object)(object)val) && !val.activeSelf) { val.SetActive(true); } } objects.Clear(); } private void ClearSavedFlags() { _fogSaved = false; _farClipSaved = false; _shadowDistanceSaved = false; _lodBiasSaved = false; _maximumLodLevelSaved = false; _ambientLightSaved = false; _uiRefreshTimer = 0f; } private static Camera GetMainCamera() { if ((Object)(object)GameDirector.instance != (Object)null && (Object)(object)GameDirector.instance.MainCamera != (Object)null) { return GameDirector.instance.MainCamera; } return Camera.main; } } } namespace SpectateRace.Config { internal static class RaceQuickStartConfig { internal static ConfigEntry? RaceQuickStartKey; internal static void Bind(ConfigFile config) { RaceQuickStartKey = config.Bind("Race Quick Start", "RaceQuickStartKey", (KeyCode)290, "Key to quickly transition to Arena Race. Host or singleplayer only."); } } internal static class RaceWorldLabelConfig { internal static ConfigEntry? ToggleKey; internal static ConfigEntry? DefaultMode; internal static ConfigEntry? HeightOffset; internal static ConfigEntry? MinScale; internal static ConfigEntry? MaxScale; internal static ConfigEntry? MinScaleDistance; internal static ConfigEntry? MaxScaleDistance; internal static ConfigEntry? HideBehindCamera; public static void Bind(ConfigFile config) { ToggleKey = config.Bind("World Labels", "ToggleKey", (KeyCode)99, "Toggle race world labels mode."); DefaultMode = config.Bind("World Labels", "DefaultMode", RaceWorldLabelMode.Top3, "Default world label mode."); HeightOffset = config.Bind("World Labels", "HeightOffset", 2.2f, "Vertical offset above the player."); MinScale = config.Bind("World Labels", "MinScale", 0.008f, "Minimum world label scale."); MaxScale = config.Bind("World Labels", "MaxScale", 0.026f, "Maximum world label scale."); MinScaleDistance = config.Bind("World Labels", "MinScaleDistance", 8f, "Distance where labels use minimum scale."); MaxScaleDistance = config.Bind("World Labels", "MaxScaleDistance", 55f, "Distance where labels reach maximum scale."); HideBehindCamera = config.Bind("World Labels", "HideBehindCamera", true, "Hide labels when they are behind the camera."); } } internal static class SpectateRaceViewConfig { internal static ConfigEntry EnableViewTweaks; internal static ConfigEntry HidePlayerMenuHead; internal static ConfigEntry HideSpectatePlayerList; internal static ConfigEntry HideSpectateHeadUI; internal static ConfigEntry DisableFog; internal static ConfigEntry NightVisionStrength; internal static ConfigEntry NightVisionWheelStep; internal static ConfigEntry SpectateCameraMaxDistance; public static void Bind(ConfigFile config) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown EnableViewTweaks = config.Bind("Spectator View", "EnableViewTweaks", true, "Enable spectator view tweaks while spectating Arena Race."); HidePlayerMenuHead = config.Bind("Spectator View", "HidePlayerMenuHead", false, "Hide player head UI while spectating Arena Race."); HideSpectatePlayerList = config.Bind("Spectator View", "HideSpectatePlayerList", false, "Hide spectate player list while spectating Arena Race."); HideSpectateHeadUI = config.Bind("Spectator View", "HideSpectateHeadUI", true, "Hide spectate head UI while spectating Arena Race."); DisableFog = config.Bind("Spectator View", "DisableFog", true, "Disable scene fog while spectating Arena Race."); SpectateCameraMaxDistance = config.Bind("Spectator View", "SpectateCameraMaxDistance", 12f, new ConfigDescription("Maximum normal spectate camera distance. Vanilla is 6.", (AcceptableValueBase)(object)new AcceptableValueRange(6f, 30f), Array.Empty())); NightVisionStrength = config.Bind("Spectator View", "NightVisionStrength", 25f, new ConfigDescription("Ambient-light based night vision strength while spectating Arena Race. 0 = off, 100 = max.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); NightVisionWheelStep = config.Bind("Spectator View", "NightVisionWheelStep", 5f, new ConfigDescription("Night vision adjustment step per mouse wheel notch while holding Alt.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 25f), Array.Empty())); } } }