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 REPORaceSpectator v1.0.0
SpectateRace.dll
Decompiled 3 hours agousing 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<RaceWorldLabelManager>())) { ((Component)this).gameObject.AddComponent<RaceWorldLabelManager>(); Logger.LogInfo((object)"[WorldLabel] Manager attached to plugin object."); } if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent<SpectateRaceViewTweaks>())) { ((Component)this).gameObject.AddComponent<SpectateRaceViewTweaks>(); Logger.LogInfo((object)"[ViewTweaks] Manager attached to plugin object."); } if (!Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent<RaceQuickStartController>())) { ((Component)this).gameObject.AddComponent<RaceQuickStartController>(); 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<PlayerAvatar> _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 <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>7__wrap1; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>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<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__0 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__0(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<Transpiler>d__0))] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>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 "<b><color=" + placeColor + ">" + ordinal + "</color></b>"; } public static string BuildColoredName(int place, string playerName) { string coloredOrdinal = GetColoredOrdinal(place); string text = EscapeRichText(playerName); if (string.IsNullOrEmpty(coloredOrdinal)) { return "<color=#FFFFFF>" + text + "</color>"; } return coloredOrdinal + " <color=#FFFFFF>" + text + "</color>"; } 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<PlayerAvatar> Placements = new List<PlayerAvatar>(); public static void Set(List<PlayerAvatar> 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<PlayerAvatar> GetPlacementsSnapshot() { return new List<PlayerAvatar>(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>(); 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>(); _canvas.renderMode = (RenderMode)2; _canvas.sortingOrder = 5000; _root = ((Component)this).gameObject.GetComponent<RectTransform>(); _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<RectTransform>(); _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<Image>(); ((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<RectTransform>(); 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<Image>(); ((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<RectTransform>(); 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<TextMeshProUGUI>(); ((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<TMP_FontAsset>(defaultTmpFont); ((Object)_cachedFont).name = "SpectateRace_LabelFont"; if (_cachedFont.fallbackFontAssetTable == null) { _cachedFont.fallbackFontAssetTable = new List<TMP_FontAsset>(); } 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>(); 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>(); 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<TMP_FontAsset>(); 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<PlayerAvatar, RaceWorldLabel> _labels = new Dictionary<PlayerAvatar, RaceWorldLabel>(); 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<PlayerAvatar> placementsSnapshot = RacePlacementCache.GetPlacementsSnapshot(); HashSet<PlayerAvatar> hashSet = new HashSet<PlayerAvatar>(); 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<PlayerAvatar> activePlayers) { List<PlayerAvatar> list = new List<PlayerAvatar>(); foreach (KeyValuePair<PlayerAvatar, RaceWorldLabel> 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<GameObject> _hiddenPlayerMenuHeads = new List<GameObject>(); private readonly List<GameObject> _hiddenSpectateHeadUis = new List<GameObject>(); private readonly List<GameObject> _hiddenSpectateListObjects = new List<GameObject>(); private readonly List<GameObject> _hiddenMenuPlayerListedObjects = new List<GameObject>(); 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<MenuSpectateList>(true); } } private void HidePlayerMenuHeads(bool includeInactive) { MenuPlayerHead[] array = Object.FindObjectsOfType<MenuPlayerHead>(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<SpectateHeadUI>(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<Canvas>())) { 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<GameObject> 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<GameObject> 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<KeyCode>? RaceQuickStartKey; internal static void Bind(ConfigFile config) { RaceQuickStartKey = config.Bind<KeyCode>("Race Quick Start", "RaceQuickStartKey", (KeyCode)290, "Key to quickly transition to Arena Race. Host or singleplayer only."); } } internal static class RaceWorldLabelConfig { internal static ConfigEntry<KeyCode>? ToggleKey; internal static ConfigEntry<RaceWorldLabelMode>? DefaultMode; internal static ConfigEntry<float>? HeightOffset; internal static ConfigEntry<float>? MinScale; internal static ConfigEntry<float>? MaxScale; internal static ConfigEntry<float>? MinScaleDistance; internal static ConfigEntry<float>? MaxScaleDistance; internal static ConfigEntry<bool>? HideBehindCamera; public static void Bind(ConfigFile config) { ToggleKey = config.Bind<KeyCode>("World Labels", "ToggleKey", (KeyCode)99, "Toggle race world labels mode."); DefaultMode = config.Bind<RaceWorldLabelMode>("World Labels", "DefaultMode", RaceWorldLabelMode.Top3, "Default world label mode."); HeightOffset = config.Bind<float>("World Labels", "HeightOffset", 2.2f, "Vertical offset above the player."); MinScale = config.Bind<float>("World Labels", "MinScale", 0.008f, "Minimum world label scale."); MaxScale = config.Bind<float>("World Labels", "MaxScale", 0.026f, "Maximum world label scale."); MinScaleDistance = config.Bind<float>("World Labels", "MinScaleDistance", 8f, "Distance where labels use minimum scale."); MaxScaleDistance = config.Bind<float>("World Labels", "MaxScaleDistance", 55f, "Distance where labels reach maximum scale."); HideBehindCamera = config.Bind<bool>("World Labels", "HideBehindCamera", true, "Hide labels when they are behind the camera."); } } internal static class SpectateRaceViewConfig { internal static ConfigEntry<bool> EnableViewTweaks; internal static ConfigEntry<bool> HidePlayerMenuHead; internal static ConfigEntry<bool> HideSpectatePlayerList; internal static ConfigEntry<bool> HideSpectateHeadUI; internal static ConfigEntry<bool> DisableFog; internal static ConfigEntry<float> NightVisionStrength; internal static ConfigEntry<float> NightVisionWheelStep; internal static ConfigEntry<float> 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<bool>("Spectator View", "EnableViewTweaks", true, "Enable spectator view tweaks while spectating Arena Race."); HidePlayerMenuHead = config.Bind<bool>("Spectator View", "HidePlayerMenuHead", false, "Hide player head UI while spectating Arena Race."); HideSpectatePlayerList = config.Bind<bool>("Spectator View", "HideSpectatePlayerList", false, "Hide spectate player list while spectating Arena Race."); HideSpectateHeadUI = config.Bind<bool>("Spectator View", "HideSpectateHeadUI", true, "Hide spectate head UI while spectating Arena Race."); DisableFog = config.Bind<bool>("Spectator View", "DisableFog", true, "Disable scene fog while spectating Arena Race."); SpectateCameraMaxDistance = config.Bind<float>("Spectator View", "SpectateCameraMaxDistance", 12f, new ConfigDescription("Maximum normal spectate camera distance. Vanilla is 6.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 30f), Array.Empty<object>())); NightVisionStrength = config.Bind<float>("Spectator View", "NightVisionStrength", 25f, new ConfigDescription("Ambient-light based night vision strength while spectating Arena Race. 0 = off, 100 = max.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); NightVisionWheelStep = config.Bind<float>("Spectator View", "NightVisionWheelStep", 5f, new ConfigDescription("Night vision adjustment step per mouse wheel notch while holding Alt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 25f), Array.Empty<object>())); } } }