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 Varkour v0.5.1
plugins/Varkour.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; using Varkour.Core; using Varkour.Editor; using Varkour.Items; using Varkour.Map; using Varkour.Net; using Varkour.Runs; using Varkour.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Dillon")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Build parkour courses in Valheim, run them, and compete on server-side leaderboards.")] [assembly: AssemblyFileVersion("0.5.1.0")] [assembly: AssemblyInformationalVersion("0.5.1")] [assembly: AssemblyProduct("Varkour")] [assembly: AssemblyTitle("Varkour")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.1.0")] [module: UnverifiableCode] namespace Varkour { [BepInPlugin("dillon.varkour", "Varkour", "0.5.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class VarkourPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private const float ErrorLogInterval = 5f; private static readonly Action ServerTick = ServerStore.Tick; private static readonly Action LabelsTick = ZoneLabels.LateTick; private static readonly string[] ClientTickNames = new string[8] { "Welcome", "ClientCourses", "ModeMachine", "CourseEditor", "RunController", "ZoneVisuals", "VarkourWindow", "CoursePins" }; private static readonly Action[] ClientTicks = new Action[8] { Welcome.Tick, ClientCourses.Tick, ModeMachine.Tick, CourseEditor.Tick, RunController.Tick, ZoneVisuals.Tick, VarkourWindow.Tick, CoursePins.Tick }; private readonly Dictionary<string, float> _lastErrorLog = new Dictionary<string, float>(); private Harmony _harmony; private bool _headless; private void Awake() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _headless = GUIManager.IsHeadless(); VarkourConfig.Bind(((BaseUnityPlugin)this).Config); VarkourLocalization.Register(); VarkourNet.Register(); HardcoreParkour.Register(_headless); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; if (!_headless) { CourseEditor.Init(); RunController.Init(); VarkourWindow.Init(); } _harmony = new Harmony("dillon.varkour"); _harmony.PatchAll(typeof(VarkourPlugin).Assembly); Log.LogInfo((object)("Varkour 0.5.1 loaded (" + (_headless ? "dedicated server" : "client") + ").")); } private void OnVanillaPrefabsAvailable() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; MarkerPieces.Register(); PoleItem.Register(); } private void Update() { Safe("ServerStore", ServerTick); if (!_headless) { for (int i = 0; i < ClientTicks.Length; i++) { Safe(ClientTickNames[i], ClientTicks[i]); } } } private void LateUpdate() { if (!_headless) { Safe("ZoneLabels", LabelsTick); } } private void OnDestroy() { ServerStore.Unload(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void LogVerbose(string message) { if (VarkourConfig.VerboseLogging != null && VarkourConfig.VerboseLogging.Value) { Log.LogInfo((object)message); } } private void Safe(string name, Action tick) { try { tick(); } catch (Exception arg) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!_lastErrorLog.TryGetValue(name, out var value) || realtimeSinceStartup - value > 5f) { _lastErrorLog[name] = realtimeSinceStartup; Log.LogError((object)$"{name} tick failed: {arg}"); } } } } } namespace Varkour.UI { internal static class VarkourWindow { private enum Tab { Courses, Leaderboards, Info } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Action <>9__61_0; public static Action <>9__61_1; public static Action <>9__61_2; public static UnityAction<bool> <>9__61_3; public static UnityAction <>9__61_4; public static UnityAction <>9__64_0; public static UnityAction <>9__64_1; public static UnityAction<string> <>9__69_0; public static Action <>9__69_1; public static Action <>9__74_0; internal void <EnsureBuilt>b__61_0() { SetTab(Tab.Courses); } internal void <EnsureBuilt>b__61_1() { SetTab(Tab.Leaderboards); } internal void <EnsureBuilt>b__61_2() { SetTab(Tab.Info); } internal void <EnsureBuilt>b__61_3(bool v) { RunController.Practice = v; } internal void <EnsureBuilt>b__61_4() { SetCursorActive(active: false); } internal void <BuildConfirm>b__64_0() { _confirm.SetActive(false); Action confirmAction = _confirmAction; _confirmAction = null; confirmAction?.Invoke(); } internal void <BuildConfirm>b__64_1() { _confirm.SetActive(false); _confirmAction = null; } internal void <BuildZoneList>b__69_0(string _) { ApplyRename(); } internal void <BuildZoneList>b__69_1() { ApplyRename(); CourseEditor.Close(); _dirty = true; } internal void <BuildLeaderboard>b__74_0() { _selectedBoardCourse = null; } } private const float Width = 900f; private const float Height = 640f; private const float RowHeight = 34f; private const int FontSize = 18; private const float EdgeInset = 30f; private const float TabGap = 12f; private const float TabY = -85f; private const float TabHeight = 36f; private const float FooterBottom = 22f; private const float HintHeight = 24f; private const float CloseHeight = 36f; private const float CloseWidth = 160f; private const float FooterGap = 6f; private const float FocusButtonWidth = 230f; private const float HintY = 34f; private const float CloseY = 70f; private const float ListBottom = 100f; private static readonly List<Course> MyDrafts = new List<Course>(); private static GameObject _panel; private static RectTransform _content; private static InputField _nameInput; private static GameObject _newCourseRow; private static Toggle _practiceToggle; private static Text _title; private static GameObject _confirm; private static Text _confirmText; private static Action _confirmAction; private static Tab _tab = Tab.Courses; private static string _selectedBoardCourse; private static int _builtRevision = -1; private static VarkourMode _builtMode; private static Tab _builtTab; private static string _builtBoardCourse; private static bool _dirty = true; private static CanvasGroup _panelGroup; private static Text _cursorHint; private static GameObject _focusButton; private static Button _addSpotButton; private static InputField _renameInput; private static Course _renameCourse; private static string _renameTextInFlight; private static bool _renameFocusInFlight; private static bool _rememberedOpen = true; private static bool _rememberedFocus = true; private static bool _typingBlock; private const float MoveButtonWidth = 34f; public static bool IsOpen { get { if ((Object)(object)_panel != (Object)null) { return _panel.activeSelf; } return false; } } public static bool CursorActive { get; private set; } public static void Init() { ModeMachine.Changed += OnModeChanged; } private static void OnModeChanged(VarkourMode previous, VarkourMode next) { if (next == VarkourMode.Off) { _rememberedOpen = IsOpen; _rememberedFocus = IsOpen && CursorActive; return; } if (previous == VarkourMode.Off && next == VarkourMode.Idle && _rememberedOpen && !IsOpen && !UiState.VanillaMenuOpen()) { Open(); SetCursorActive(_rememberedFocus); return; } if (next == VarkourMode.Editing && IsOpen) { SetCursorActive(active: false); } if (previous == VarkourMode.Editing) { ApplyRename(); } } private static void ApplyRename() { if ((Object)(object)_renameInput != (Object)null && _renameCourse != null) { CourseEditor.Rename(_renameCourse, _renameInput.text); } } public static void Tick() { VarkourMode current = ModeMachine.Current; bool flag = current == VarkourMode.Idle || current == VarkourMode.Editing; if (IsOpen && !flag) { Close(); return; } if (VarkourInput.Down(VarkourConfig.WindowKey)) { VarkourPlugin.LogVerbose($"Window key: mode={current}, open={IsOpen}, menuOpen={UiState.VanillaMenuOpen()}."); if (IsOpen) { Close(); return; } if (flag && !UiState.VanillaMenuOpen()) { Open(); } } if (!IsOpen) { return; } if (!_typingBlock && VarkourInput.Down(VarkourConfig.CursorToggleKey)) { SetCursorActive(!CursorActive); } SetTypingBlock(((Object)(object)_nameInput != (Object)null && _nameInput.isFocused) || ((Object)(object)_renameInput != (Object)null && _renameInput.isFocused)); if (_dirty || _builtRevision != ClientCourses.Revision || _builtMode != current || _builtTab != _tab || _builtBoardCourse != _selectedBoardCourse) { Rebuild(); } if ((Object)(object)_addSpotButton != (Object)null && current == VarkourMode.Editing) { bool flag2 = CourseEditor.CanAddCheckpointAtPlayer(); if (((Selectable)_addSpotButton).interactable != flag2) { ((Selectable)_addSpotButton).interactable = flag2; } } } public static void Open() { if (EnsureBuilt()) { _panel.SetActive(true); _confirm.SetActive(false); SetCursorActive(active: true); _practiceToggle.SetIsOnWithoutNotify(RunController.Practice); _dirty = true; if (_tab == Tab.Leaderboards && _selectedBoardCourse != null) { VarkourNet.RequestLeaderboard(_selectedBoardCourse); } } } public static void Close() { if (!((Object)(object)_panel == (Object)null) && _panel.activeSelf) { _panel.SetActive(false); SetTypingBlock(block: false); SetCursorActive(active: false); } } private static void SetCursorActive(bool active) { if (CursorActive != active || !((Object)(object)_panelGroup != (Object)null)) { CursorActive = active; if ((Object)(object)_panelGroup != (Object)null) { _panelGroup.interactable = active; _panelGroup.blocksRaycasts = active; _panelGroup.alpha = (active ? 1f : 0.55f); } if (!active) { SetTypingBlock(block: false); } UpdateCursorHint(); } } private static void UpdateCursorHint() { if (!((Object)(object)_cursorHint == (Object)null)) { string text = VarkourInput.KeyName(VarkourConfig.CursorToggleKey); _cursorHint.text = VarkourLocalization.T(CursorActive ? "varkour_hint_to_build" : "varkour_hint_to_click", text); if ((Object)(object)_focusButton != (Object)null && _focusButton.activeSelf != CursorActive) { _focusButton.SetActive(CursorActive); } } } private static void SetTypingBlock(bool block) { if (_typingBlock != block) { _typingBlock = block; GUIManager.BlockInput(block); } } private static bool EnsureBuilt() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Expected O, but got Unknown //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Expected O, but got Unknown //IL_0592: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05b0: Unknown result type (might be due to invalid IL or missing references) //IL_05be: Unknown result type (might be due to invalid IL or missing references) //IL_05c4: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Unknown result type (might be due to invalid IL or missing references) //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Expected O, but got Unknown if ((Object)(object)_panel != (Object)null) { return true; } GameObject customGUIFront = GUIManager.CustomGUIFront; if ((Object)(object)customGUIFront == (Object)null) { VarkourPlugin.Log.LogWarning((object)"Cannot open the Varkour window yet: Jötunn's CustomGUIFront is not available."); return false; } GUIManager instance = GUIManager.Instance; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); _panel = instance.CreateWoodpanel(customGUIFront.transform, val, val, Vector2.zero, 900f, 640f, true); ((Object)_panel).name = "Varkour_Window"; _title = instance.CreateText(VarkourLocalization.T("varkour_window_title"), _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -35f), instance.NorseBold, 32, instance.ValheimOrange, true, Color.black, 860f, 44f, false).GetComponent<Text>(); _title.alignment = (TextAnchor)4; _panelGroup = _panel.GetComponent<CanvasGroup>() ?? _panel.AddComponent<CanvasGroup>(); float left = -420f; left = TopButton(VarkourLocalization.T("varkour_tab_courses"), left, 170f, delegate { SetTab(Tab.Courses); }); left = TopButton(VarkourLocalization.T("varkour_tab_leaderboards"), left, 180f, delegate { SetTab(Tab.Leaderboards); }); left = TopButton(VarkourLocalization.T("varkour_tab_info"), left, 110f, delegate { SetTab(Tab.Info); }); left += 36f; GameObject obj = instance.CreateToggle(_panel.transform, 28f, 28f); RectTransform val2 = (RectTransform)obj.transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 1f); val2.anchorMax = val3; val2.anchorMin = val3; val2.anchoredPosition = new Vector2(left + 14f, -85f); _practiceToggle = obj.GetComponent<Toggle>(); _practiceToggle.isOn = RunController.Practice; ((UnityEvent<bool>)(object)_practiceToggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v) { RunController.Practice = v; }); left += 38f; instance.CreateText(VarkourLocalization.T("varkour_practice"), _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(left + 95f, -85f), instance.AveriaSerifBold, 18, instance.ValheimBeige, true, Color.black, 190f, 30f, false).GetComponent<Text>().alignment = (TextAnchor)3; _newCourseRow = new GameObject("NewCourse", new Type[1] { typeof(RectTransform) }); _newCourseRow.transform.SetParent(_panel.transform, false); RectTransform val4 = (RectTransform)_newCourseRow.transform; ((Vector2)(ref val3))..ctor(0.5f, 1f); val4.anchorMax = val3; val4.anchorMin = val3; val4.anchoredPosition = new Vector2(0f, -130f); val4.sizeDelta = new Vector2(840f, 36f); _nameInput = instance.CreateInputField(_newCourseRow.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(220f, 0f), (ContentType)0, VarkourLocalization.T("varkour_course_name_placeholder"), 18, 440f, 34f).GetComponent<InputField>(); _nameInput.characterLimit = VarkourConfig.MaxCourseNameLength.Value; ((UnityEvent)instance.CreateButton(VarkourLocalization.T("varkour_new_course"), _newCourseRow.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-110f, 0f), 200f, 34f).GetComponent<Button>().onClick).AddListener(new UnityAction(OnNewCourse)); _content = BuildScrollList(instance); float num = -207f; _focusButton = instance.CreateButton(VarkourLocalization.T("varkour_focus_game", VarkourInput.KeyName(VarkourConfig.CursorToggleKey)), _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(num, 70f), 230f, 36f); ButtonClickedEvent onClick = _focusButton.GetComponent<Button>().onClick; object obj2 = <>c.<>9__61_4; if (obj2 == null) { UnityAction val5 = delegate { SetCursorActive(active: false); }; <>c.<>9__61_4 = val5; obj2 = (object)val5; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); ((UnityEvent)instance.CreateButton(VarkourLocalization.T("varkour_close", VarkourInput.KeyName(VarkourConfig.WindowKey)), _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 70f), 160f, 36f).GetComponent<Button>().onClick).AddListener(new UnityAction(Close)); _cursorHint = instance.CreateText(string.Empty, _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 34f), instance.AveriaSerifBold, 16, instance.ValheimBeige, true, Color.black, 840f, 24f, false).GetComponent<Text>(); _cursorHint.alignment = (TextAnchor)4; BuildConfirm(instance); _panel.SetActive(false); return true; } private static RectTransform BuildScrollList(GUIManager gui) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("List", new Type[3] { typeof(RectTransform), typeof(Image), typeof(ScrollRect) }); val.transform.SetParent(_panel.transform, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.pivot = new Vector2(0.5f, 0.5f); val2.offsetMin = new Vector2(30f, 100f); val2.offsetMax = new Vector2(-30f, -155f); ((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.3f); GameObject val3 = new GameObject("Viewport", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }); val3.transform.SetParent(val.transform, false); RectTransform val4 = (RectTransform)val3.transform; val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.pivot = new Vector2(0f, 1f); val4.offsetMin = Vector2.zero; val4.offsetMax = new Vector2(-18f, 0f); GameObject val5 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); val5.transform.SetParent(val3.transform, false); RectTransform val6 = (RectTransform)val5.transform; val6.anchorMin = new Vector2(0f, 1f); val6.anchorMax = new Vector2(1f, 1f); val6.pivot = new Vector2(0.5f, 1f); val6.anchoredPosition = Vector2.zero; val6.sizeDelta = Vector2.zero; VerticalLayoutGroup obj = val5.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f; ((LayoutGroup)obj).padding = new RectOffset(8, 8, 8, 8); ContentSizeFitter obj2 = val5.AddComponent<ContentSizeFitter>(); obj2.horizontalFit = (FitMode)0; obj2.verticalFit = (FitMode)2; GameObject obj3 = DefaultControls.CreateScrollbar(gui.ValheimControlResources); obj3.transform.SetParent(val.transform, false); RectTransform val7 = (RectTransform)obj3.transform; val7.anchorMin = new Vector2(1f, 0f); val7.anchorMax = new Vector2(1f, 1f); val7.pivot = new Vector2(1f, 0.5f); val7.sizeDelta = new Vector2(14f, 0f); val7.anchoredPosition = Vector2.zero; Scrollbar component = obj3.GetComponent<Scrollbar>(); component.direction = (Direction)2; gui.ApplyScrollbarStyle(component); ScrollRect component2 = val.GetComponent<ScrollRect>(); component2.viewport = val4; component2.content = val6; component2.horizontal = false; component2.vertical = true; component2.movementType = (MovementType)2; component2.scrollSensitivity = 30f; component2.verticalScrollbar = component; component2.verticalScrollbarVisibility = (ScrollbarVisibility)0; return val6; } private static float TopButton(string text, float left, float width, Action onClick) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown ((UnityEvent)GUIManager.Instance.CreateButton(text, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(left + width / 2f, -85f), width, 36f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { onClick(); }); return left + width + 12f; } private static void BuildConfirm(GUIManager gui) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); _confirm = gui.CreateWoodpanel(_panel.transform, val, val, Vector2.zero, 520f, 220f, false); ((Object)_confirm).name = "Confirm"; _confirmText = gui.CreateText(string.Empty, _confirm.transform, val, val, new Vector2(0f, 30f), gui.AveriaSerifBold, 18, gui.ValheimBeige, true, Color.black, 460f, 110f, false).GetComponent<Text>(); _confirmText.alignment = (TextAnchor)4; ButtonClickedEvent onClick = gui.CreateButton(VarkourLocalization.T("varkour_yes"), _confirm.transform, val, val, new Vector2(-90f, -60f), 150f, 36f).GetComponent<Button>().onClick; object obj = <>c.<>9__64_0; if (obj == null) { UnityAction val2 = delegate { _confirm.SetActive(false); Action confirmAction = _confirmAction; _confirmAction = null; confirmAction?.Invoke(); }; <>c.<>9__64_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ButtonClickedEvent onClick2 = gui.CreateButton(VarkourLocalization.T("varkour_no"), _confirm.transform, val, val, new Vector2(90f, -60f), 150f, 36f).GetComponent<Button>().onClick; object obj2 = <>c.<>9__64_1; if (obj2 == null) { UnityAction val3 = delegate { _confirm.SetActive(false); _confirmAction = null; }; <>c.<>9__64_1 = val3; obj2 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); _confirm.SetActive(false); } private static void Confirm(string text, Action action) { _confirmText.text = text; _confirmAction = action; _confirm.SetActive(true); _confirm.transform.SetAsLastSibling(); } private static void SetTab(Tab tab) { _tab = tab; if (tab == Tab.Leaderboards && _selectedBoardCourse != null) { VarkourNet.RequestLeaderboard(_selectedBoardCourse); } _dirty = true; } private static void Rebuild() { _dirty = false; _builtRevision = ClientCourses.Revision; _builtMode = ModeMachine.Current; _builtTab = _tab; _builtBoardCourse = _selectedBoardCourse; int num; object renameTextInFlight; if ((Object)(object)_renameInput != (Object)null && _renameCourse != null) { num = ((_renameCourse == CourseEditor.Open) ? 1 : 0); if (num != 0) { renameTextInFlight = _renameInput.text; goto IL_0061; } } else { num = 0; } renameTextInFlight = null; goto IL_0061; IL_0061: _renameTextInFlight = (string)renameTextInFlight; _renameFocusInFlight = num != 0 && _renameInput.isFocused; for (int num2 = ((Transform)_content).childCount - 1; num2 >= 0; num2--) { Object.Destroy((Object)(object)((Component)((Transform)_content).GetChild(num2)).gameObject); } _addSpotButton = null; _renameInput = null; _renameCourse = null; bool flag = ModeMachine.Current == VarkourMode.Editing; _newCourseRow.SetActive(_tab == Tab.Courses && !flag); UpdateCursorHint(); if (_tab == Tab.Info) { BuildInfo(); } else if (_tab == Tab.Courses) { if (flag) { BuildZoneList(); } else { BuildCourseList(); } } else if (_selectedBoardCourse != null && ClientCourses.GetPublished(_selectedBoardCourse) != null) { BuildLeaderboard(ClientCourses.GetPublished(_selectedBoardCourse)); } else { _selectedBoardCourse = null; _builtBoardCourse = null; BuildBoardCourseList(); } } private static void BuildCourseList() { if (!ClientCourses.HasWorld) { Label(VarkourLocalization.T("varkour_loading")); return; } long localPlayerId = ClientCourses.LocalPlayerId; int num = 0; ClientCourses.GetMyDrafts(MyDrafts); foreach (Course myDraft in MyDrafts) { num++; Course course = myDraft; RectTransform row = Row(); RowText(row, course.Name + " <color=#A0A0A0>" + VarkourLocalization.T("varkour_draft") + " · " + ZoneSummary(course) + "</color>"); VisibilityButton(row, course); RowButton(row, VarkourLocalization.T("varkour_edit"), 110f, delegate { if (CourseEditor.Begin(course)) { _tab = Tab.Courses; } }); RowButton(row, VarkourLocalization.T("varkour_delete"), 110f, delegate { Confirm(VarkourLocalization.T("varkour_confirm_delete", course.Name), delegate { ClientCourses.DeleteDraft(course.Id); }); }); } foreach (Course item in ClientCourses.Published) { if (item.AuthorId != localPlayerId) { continue; } num++; Course course2 = item; RectTransform row2 = Row(); RowText(row2, course2.Name + " <color=#80C0FF>" + VarkourLocalization.T("varkour_published") + " · " + ZoneSummary(course2) + "</color>"); VisibilityButton(row2, course2); RowButton(row2, VarkourLocalization.T("varkour_edit"), 110f, delegate { Confirm(VarkourLocalization.T("varkour_confirm_unpublish", course2.Name), delegate { CourseEditor.BeginFromPublished(course2); _tab = Tab.Courses; }); }); RowButton(row2, VarkourLocalization.T("varkour_delete"), 110f, delegate { Confirm(VarkourLocalization.T("varkour_confirm_delete", course2.Name), delegate { VarkourNet.SendDelete(course2.Id); }); }); } if (num == 0) { Label(VarkourLocalization.T("varkour_no_courses")); } } private static void BuildZoneList() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) Course open = CourseEditor.Open; if (open == null) { return; } RectTransform val = Row(); RowFixedText(val, "<b>" + VarkourLocalization.T("varkour_editing") + "</b>", 170f); GameObject obj = GUIManager.Instance.CreateInputField((Transform)(object)val, Vector2.zero, Vector2.zero, Vector2.zero, (ContentType)0, VarkourLocalization.T("varkour_course_name_placeholder"), 18, 100f, 34f); LayoutElement obj2 = obj.AddComponent<LayoutElement>(); obj2.minWidth = 200f; obj2.preferredWidth = 200f; obj2.flexibleWidth = 1f; obj2.preferredHeight = 34f; _renameInput = obj.GetComponent<InputField>(); _renameInput.characterLimit = VarkourConfig.MaxCourseNameLength.Value; _renameInput.text = _renameTextInFlight ?? open.Name; _renameCourse = open; if (_renameFocusInFlight) { _renameInput.ActivateInputField(); } _renameTextInFlight = null; _renameFocusInFlight = false; ((UnityEvent<string>)(object)_renameInput.onEndEdit).AddListener((UnityAction<string>)delegate { ApplyRename(); }); RowButton(val, VarkourLocalization.T("varkour_close_editor"), 180f, delegate { ApplyRename(); CourseEditor.Close(); _dirty = true; }); Label("<color=#A0A0A0>" + VarkourLocalization.T("varkour_zone_hint", RemoveKeyName()) + "</color>"); if (!open.IsRunnable) { Label("<color=#FFB060>" + VarkourLocalization.T("varkour_course_invalid") + "</color>"); } for (int num = 0; num < open.Zones.Count; num++) { int index = num; Zone zone = open.Zones[num]; RectTransform row = Row(); string text = ((zone.Type == ZoneType.Checkpoint) ? VarkourLocalization.T("varkour_spot", open.CheckpointNumberAt(num)) : CourseEditor.LabelFor(open, num)); if (zone == CourseEditor.SelectedZone) { text = "<color=#FFE040><b>" + text + "</b></color>"; } RowText(row, text, delegate { CourseEditor.SelectAt(index); }); if (zone.Type == ZoneType.Checkpoint) { RowButton(row, VarkourLocalization.T("varkour_up"), 34f, delegate { CourseEditor.MoveCheckpoint(index, -1); }, CourseEditor.CanMoveCheckpoint(open, index, -1)); RowButton(row, VarkourLocalization.T("varkour_down"), 34f, delegate { CourseEditor.MoveCheckpoint(index, 1); }, CourseEditor.CanMoveCheckpoint(open, index, 1)); } else { Spacer(row, 74f); } RowButton(row, "-", 34f, delegate { CourseEditor.AdjustRadius(index, 0f - VarkourConfig.ZoneRadiusStep.Value); }); RowFixedText(row, zone.Radius.ToString("0.0") + " m", 64f); RowButton(row, "+", 34f, delegate { CourseEditor.AdjustRadius(index, VarkourConfig.ZoneRadiusStep.Value); }); RowButton(row, VarkourLocalization.T("varkour_zone_to_player"), 196f, delegate { CourseEditor.MoveToPlayer(index); }); RowButton(row, VarkourLocalization.T("varkour_delete"), 80f, delegate { CourseEditor.RemoveAt(index); }); } _addSpotButton = RowButton(Row(), VarkourLocalization.T("varkour_add_spot_here"), 320f, CourseEditor.AddCheckpointAtPlayer, CourseEditor.CanAddCheckpointAtPlayer()); } private static void BuildInfo() { Label("<b>" + VarkourLocalization.T("varkour_info_keys") + "</b>"); InfoRow(VarkourInput.KeyName(VarkourConfig.WindowKey), "varkour_info_window"); InfoRow(VarkourInput.KeyName(VarkourConfig.CursorToggleKey), "varkour_info_cursor"); InfoRow(VarkourInput.KeyName(VarkourConfig.RestartKey), "varkour_info_restart"); InfoRow(VarkourInput.KeyName(VarkourConfig.CancelKey), "varkour_info_cancel"); InfoRow(VarkourInput.KeyName(VarkourConfig.PracticeRespawnKey), "varkour_info_practice"); InfoRow(VarkourLocalization.T("varkour_info_rmb"), "varkour_info_menu"); InfoRow(VarkourLocalization.T("varkour_info_m1"), "varkour_info_place"); InfoRow(VarkourLocalization.T("varkour_info_shift_scroll"), "varkour_info_size"); InfoRow(RemoveKeyName(), "varkour_info_remove"); Label(string.Empty); Label("<b>" + VarkourLocalization.T("varkour_info_buff") + "</b>"); Label(VarkourLocalization.T("varkour_info_buff_desc")); InfoSection("varkour_info_build", 3); InfoSection("varkour_info_publish", 3); InfoSection("varkour_info_run", 3); } private static void InfoSection(string token, int lines) { Label(string.Empty); Label("<b>" + VarkourLocalization.T(token) + "</b>"); for (int i = 1; i <= lines; i++) { Label(VarkourLocalization.T(token + i)); } } private static void InfoRow(string key, string token) { RectTransform row = Row(); RowFixedText(row, "<color=#FFE040>" + key + "</color>", 170f); RowText(row, VarkourLocalization.T(token)); } private static void BuildBoardCourseList() { IReadOnlyList<Course> published = ClientCourses.Published; if (published.Count == 0) { Label(VarkourLocalization.T(ClientCourses.HasWorld ? "varkour_no_published" : "varkour_loading")); return; } foreach (Course item in published) { Course course = item; RectTransform row = Row(); RowText(row, course.Name + " <color=#A0A0A0>" + CourseStats(course) + "</color>"); VisibilityButton(row, course); RowButton(row, VarkourLocalization.T("varkour_select"), 110f, delegate { _selectedBoardCourse = course.Id; VarkourNet.RequestLeaderboard(course.Id); }); } } private static void BuildLeaderboard(Course course) { RectTransform row = Row(); RowButton(row, "<", 44f, delegate { _selectedBoardCourse = null; }); RowText(row, "<b>" + course.Name + "</b> <color=#A0A0A0>" + CourseStats(course) + "</color>"); RowButton(row, VarkourLocalization.T("varkour_show_on_map"), 170f, delegate { ShowOnMap(course); }); if (course.AuthorId == ClientCourses.LocalPlayerId || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.LocalPlayerIsAdminOrHost())) { RowButton(row, VarkourLocalization.T("varkour_delete"), 100f, delegate { Confirm(VarkourLocalization.T("varkour_confirm_delete", course.Name), delegate { VarkourNet.SendDelete(course.Id); _selectedBoardCourse = null; }); }); } LeaderboardView leaderboard = ClientCourses.GetLeaderboard(course.Id); if (leaderboard == null) { Label(VarkourLocalization.T("varkour_loading")); return; } if (leaderboard.Top.Count == 0) { Label(VarkourLocalization.T("varkour_no_times")); } for (int num = 0; num < leaderboard.Top.Count; num++) { RunRecord runRecord = leaderboard.Top[num]; RectTransform row2 = Row(); string text = "#" + (num + 1) + " " + runRecord.PlayerName + " " + VarkourLocalization.FormatTime(runRecord.TimeMs); if (runRecord.PlayerId == ClientCourses.LocalPlayerId) { text = "<color=#FFE040>" + text + "</color>"; } RowText(row2, text); } if (leaderboard.Own != null && leaderboard.OwnRank > leaderboard.Top.Count) { Label(VarkourLocalization.T("varkour_your_best", leaderboard.OwnRank, VarkourLocalization.FormatTime(leaderboard.Own.TimeMs))); } } private static void ShowOnMap(Course course) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) Zone start = course.Start; if (start != null && !((Object)(object)Minimap.instance == (Object)null)) { Close(); Minimap.instance.ShowPointOnMap(start.Position); } } private static string RemoveKeyName() { string text = ((Localization.instance != null) ? Localization.instance.GetBoundKeyString("Remove", true) : null); if (!string.IsNullOrEmpty(text)) { return text; } return "Remove"; } private static string ZoneSummary(Course c) { return c.CheckpointCount + " checkpoint(s)" + (c.IsRunnable ? string.Empty : " · !"); } private static string CourseStats(Course c) { return VarkourLocalization.T("varkour_by_author", c.AuthorName) + " · " + VarkourLocalization.T("varkour_runs", c.RunCount); } private static void OnNewCourse() { string text = CourseName.Clean(_nameInput.text, VarkourConfig.MaxCourseNameLength.Value); if (text.Length == 0) { Notify.Center(VarkourLocalization.T("varkour_msg_name_required")); return; } if (!ClientCourses.HasWorld) { Notify.Center(VarkourLocalization.T("varkour_loading")); return; } Course draft = ClientCourses.CreateDraft(text); _nameInput.text = string.Empty; CourseEditor.Begin(draft); _dirty = true; } private static RectTransform Row() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)_content, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f; val.AddComponent<LayoutElement>().minHeight = 34f; return (RectTransform)val.transform; } private static void RowText(RectTransform row, string text, Action onClick = null) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown GameObject val = GUIManager.Instance.CreateText(text, (Transform)(object)row, Vector2.zero, Vector2.one, Vector2.zero, GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimBeige, true, Color.black, 100f, 34f, false); Text component = val.GetComponent<Text>(); component.alignment = (TextAnchor)3; component.supportRichText = true; if (onClick != null) { ((Graphic)component).raycastTarget = true; Button obj = val.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)component; ((Selectable)obj).transition = (Transition)0; ((UnityEvent)obj.onClick).AddListener((UnityAction)delegate { onClick(); _dirty = true; }); } component.horizontalOverflow = (HorizontalWrapMode)0; component.verticalOverflow = (VerticalWrapMode)1; ((RectTransform)val.transform).pivot = new Vector2(0f, 0.5f); LayoutElement obj2 = val.AddComponent<LayoutElement>(); obj2.minWidth = 80f; obj2.preferredWidth = 80f; obj2.flexibleWidth = 1f; } private static Button RowButton(RectTransform row, string text, float width, Action onClick, bool enabled = true) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown GameObject obj = GUIManager.Instance.CreateButton(text, (Transform)(object)row, Vector2.zero, Vector2.zero, Vector2.zero, width, 34f); LayoutElement obj2 = obj.AddComponent<LayoutElement>(); obj2.preferredWidth = width; obj2.minWidth = width; obj2.preferredHeight = 34f; Button component = obj.GetComponent<Button>(); ((Selectable)component).interactable = enabled; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { try { onClick(); } catch (Exception arg) { VarkourPlugin.Log.LogError((object)$"Window action failed: {arg}"); } _dirty = true; }); return component; } private static void RowFixedText(RectTransform row, string text, float width) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GUIManager.Instance.CreateText(text, (Transform)(object)row, Vector2.zero, Vector2.one, Vector2.zero, GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimBeige, true, Color.black, width, 34f, false); obj.GetComponent<Text>().alignment = (TextAnchor)4; LayoutElement obj2 = obj.AddComponent<LayoutElement>(); obj2.preferredWidth = width; obj2.minWidth = width; obj2.preferredHeight = 34f; } private static void VisibilityButton(RectTransform row, Course course) { bool hidden = ClientCourses.IsHidden(course.Id); RowButton(row, VarkourLocalization.T(hidden ? "varkour_show" : "varkour_hide"), 80f, delegate { ClientCourses.SetHidden(course.Id, !hidden); }); } private static void Spacer(RectTransform row, float width) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Spacer", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)row, false); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = width; obj.minWidth = width; obj.preferredHeight = 34f; } private static void Label(string text) { RowText(Row(), text); } } } namespace Varkour.Runs { internal static class RunController { private enum Phase { AwaitExit, Timing } private const float RuleCheckInterval = 0.5f; private const float HudInterval = 0.05f; private const float TeleportJumpDistance = 40f; private const float LeaderboardRequestInterval = 30f; private static readonly List<Course> Visible = new List<Course>(); private static readonly List<long> Splits = new List<long>(); private static readonly StringBuilder Sb = new StringBuilder(256); private static readonly Dictionary<string, float> LastLeaderboardRequest = new Dictionary<string, float>(); private static Course _candidate; private static float _stillTime; private static int _lastCountShown = -1; private static string _idleReason; private static float _nextIdleRuleCheck; private static Phase _phase; private static double _goTime; private static double _timerStart; private static int _lastHitIndex; private static string _unrankedReason; private static float _nextRuleCheck; private static Vector3 _lastPos; private static int _runCounter; private static int _courseRevisionSeen; private static float _nextHud; private static Course _lastCourse; private const float CheckpointGrace = 0.3f; public static bool Practice { get; set; } public static Course ActiveCourse { get; private set; } public static int NextZoneIndex { get; private set; } = -1; public static bool AwaitingExit { get { if (ModeMachine.Current == VarkourMode.Running) { return _phase == Phase.AwaitExit; } return false; } } public static int VisualStep { get { if (ModeMachine.Current != VarkourMode.Running) { return -1; } return _runCounter * 1000 + NextZoneIndex + (AwaitingExit ? 500 : 0); } } private static double Clock => Time.unscaledTimeAsDouble; public static void Init() { ModeMachine.Changed += OnModeChanged; } private static void OnModeChanged(VarkourMode previous, VarkourMode next) { if (previous == VarkourMode.Running && next == VarkourMode.Off && ActiveCourse != null) { Player localPlayer = Player.m_localPlayer; Notify.Center(VarkourLocalization.T(((Object)(object)localPlayer != (Object)null && ((Character)localPlayer).IsDead()) ? "varkour_msg_cancel_death" : "varkour_msg_cancel_unequip")); ClearRun(); } if (next != VarkourMode.Idle) { ResetCountdown(); } if (next == VarkourMode.Off || next == VarkourMode.Editing) { RunHud.SetMain(null); } if (next == VarkourMode.Off) { RunHud.HideResults(); } } public static void Tick() { ModTeleport.ClearIfDone(); RunHud.Tick(); switch (ModeMachine.Current) { case VarkourMode.Idle: HandleKeys(); if (ModeMachine.Current == VarkourMode.Idle) { TickIdle(); } break; case VarkourMode.Running: HandleKeys(); if (ModeMachine.Current == VarkourMode.Running) { TickRunning(); } break; } } private static void HandleKeys() { if (UiState.WorldInputBlocked()) { return; } if (VarkourInput.Down(VarkourConfig.CancelKey)) { if (ModeMachine.Current == VarkourMode.Running) { Cancel("varkour_msg_cancelled"); } else { ResetCountdown(); } } else if (VarkourInput.Down(VarkourConfig.RestartKey)) { Restart(); } else if (VarkourInput.Down(VarkourConfig.PracticeRespawnKey)) { PracticeRespawn(); } } private static void Restart() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Course course = ((ModeMachine.Current == VarkourMode.Running) ? ActiveCourse : (_candidate ?? _lastCourse)); course = Refresh(course); if (course != null && course.Start != null) { if (ModeMachine.Current == VarkourMode.Running) { ClearRun(); ModeMachine.ReturnToIdle(); } ResetCountdown(); ModTeleport.To(course.Start.Position, FacingFrom(course, 0)); } } private static void PracticeRespawn() { //IL_004f: 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) if (Practice && ModeMachine.Current == VarkourMode.Running && ActiveCourse != null) { int index = ((_phase == Phase.Timing) ? Mathf.Clamp(_lastHitIndex, 0, ActiveCourse.Zones.Count - 1) : 0); ModTeleport.To(ActiveCourse.Zones[index].Position, FacingFrom(ActiveCourse, index)); } } private static Quaternion FacingFrom(Course course, int index) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (index + 1 < course.Zones.Count) { Vector3 val = course.Zones[index + 1].Position - course.Zones[index].Position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { return Quaternion.LookRotation(((Vector3)(ref val)).normalized); } } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer != (Object)null)) { return Quaternion.identity; } return ((Component)localPlayer).transform.rotation; } private static void TickIdle() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || UiState.WorldInputBlocked()) { ResetCountdown(); RunHud.SetMain(null); return; } Course course = FindStartZoneCourse(((Component)localPlayer).transform.position); if (course != _candidate) { ResetCountdown(); _candidate = course; } if (course == null) { RunHud.SetMain(null); return; } if (!course.IsRunnable) { RunHud.SetMain(course.Name + "\n" + VarkourLocalization.T("varkour_course_invalid")); return; } MaybeRequestLeaderboard(course); int num; if (((Character)localPlayer).IsOnGround()) { num = ((HorizontalSpeed(localPlayer) < VarkourConfig.StillSpeedThreshold.Value) ? 1 : 0); if (num != 0) { _stillTime += Time.deltaTime; goto IL_00c0; } } else { num = 0; } _stillTime = 0f; _lastCountShown = -1; goto IL_00c0; IL_00c0: int value = VarkourConfig.CountdownSeconds.Value; string text = null; if (num != 0) { int num2 = Mathf.CeilToInt((float)value - _stillTime); if (num2 != _lastCountShown && num2 > 0) { _lastCountShown = num2; RunFeedback.Tick(); } if (_stillTime >= (float)value) { StartRun(course); return; } text = VarkourLocalization.T("varkour_hud_ready"); } if (!(Time.time < _nextHud)) { if (Time.time >= _nextIdleRuleCheck) { _nextIdleRuleCheck = Time.time + 0.5f; _idleReason = RunRules.GetUnrankedReason(localPlayer); } _nextHud = Time.time + 0.05f; Sb.Length = 0; Sb.Append(VarkourLocalization.T("varkour_hud_course", course.Name)); if (ClientCourses.IsDraft(course)) { Sb.Append(" (").Append(VarkourLocalization.T("varkour_draft")).Append(')'); } Sb.Append('\n'); if (text != null) { Sb.Append("<size=40>").Append(text).Append("</size>"); } else { Sb.Append(VarkourLocalization.T("varkour_hud_stand_still")); } Sb.Append('\n').Append(VarkourLocalization.T("varkour_hud_next", 0, course.Zones.Count - 1)); Sb.Append(" ").Append(PbText(course)).Append('\n') .Append(RecordText(course)); if (_idleReason != null) { Sb.Append("\n<color=#FFB060>").Append(VarkourLocalization.T("varkour_hud_unranked", _idleReason)).Append("</color>"); } RunHud.SetMain(Sb.ToString()); } } private static Course FindStartZoneCourse(Vector3 pos) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) ClientCourses.GetShown(Visible); Course result = null; float num = float.MaxValue; foreach (Course item in Visible) { Zone start = item.Start; if (start != null && InZone(start, pos)) { float num2 = HorizontalDistance(start.Position, pos); if (num2 < num) { num = num2; result = item; } } } return result; } private static void ResetCountdown() { _candidate = null; _stillTime = 0f; _lastCountShown = -1; } private static void MaybeRequestLeaderboard(Course course) { if (!ClientCourses.IsDraft(course) && ClientCourses.GetLeaderboard(course.Id) == null && (!LastLeaderboardRequest.TryGetValue(course.Id, out var value) || !(Time.time - value < 30f))) { LastLeaderboardRequest[course.Id] = Time.time; VarkourNet.RequestLeaderboard(course.Id); } } private static void StartRun(Course course) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (ModeMachine.TryEnterRunning()) { Player localPlayer = Player.m_localPlayer; ResetCountdown(); RunHud.HideResults(); ActiveCourse = course; _lastCourse = course; _phase = Phase.AwaitExit; _goTime = Clock; _timerStart = 0.0; _lastHitIndex = 0; NextZoneIndex = 1; Splits.Clear(); _runCounter++; _courseRevisionSeen = ClientCourses.Revision; _unrankedReason = RunRules.GetUnrankedReason(localPlayer); _nextRuleCheck = Time.time + 0.5f; _lastPos = ((Component)localPlayer).transform.position; _nextHud = 0f; RunFeedback.Tick(); } } private static void TickRunning() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_005a: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Course activeCourse = ActiveCourse; if ((Object)(object)localPlayer == (Object)null || activeCourse == null) { Cancel(null); return; } if (((Character)localPlayer).IsDead()) { Cancel("varkour_msg_cancel_death"); return; } Vector3 position = ((Component)localPlayer).transform.position; Vector3 val = position - _lastPos; bool flag = ((Vector3)(ref val)).sqrMagnitude > 1600f; _lastPos = position; if (!ModTeleport.InProgress && (((Character)localPlayer).IsTeleporting() || flag)) { Cancel("varkour_msg_cancel_teleport"); return; } if (Clock - _goTime > (double)VarkourConfig.RunTimeoutSeconds.Value) { Cancel("varkour_msg_cancel_timeout"); return; } if (_courseRevisionSeen != ClientCourses.Revision) { _courseRevisionSeen = ClientCourses.Revision; Course course = Refresh(activeCourse); if (course == null || course.Version != activeCourse.Version) { Cancel("varkour_msg_cancelled"); return; } } if (Time.time >= _nextRuleCheck) { _nextRuleCheck = Time.time + 0.5f; if (_unrankedReason == null) { _unrankedReason = RunRules.GetUnrankedReason(localPlayer); } } if (_phase == Phase.AwaitExit) { if (!InZone(activeCourse.Start, position)) { _phase = Phase.Timing; _timerStart = Clock; RunFeedback.Go(); Notify.Center(VarkourLocalization.T("varkour_hud_go")); } } else if (!ModTeleport.InProgress) { Zone zone = activeCourse.Zones[NextZoneIndex]; if (InZone(zone, position)) { long num = ElapsedMs(); Splits.Add(num); _lastHitIndex = NextZoneIndex; if (zone.Type == ZoneType.End) { Finish(activeCourse, num); return; } NextZoneIndex++; RunFeedback.ZoneHit(zone.Position); } } UpdateRunHud(activeCourse); } private static long ElapsedMs() { if (_phase != Phase.Timing) { return 0L; } return (long)((Clock - _timerStart) * 1000.0); } private static void UpdateRunHud(Course course) { if (!(Time.time < _nextHud)) { _nextHud = Time.time + 0.05f; Sb.Length = 0; Sb.Append(VarkourLocalization.T("varkour_hud_course", course.Name)).Append('\n'); if (_phase == Phase.AwaitExit) { Sb.Append("<size=40>").Append(VarkourLocalization.T("varkour_hud_set")).Append("</size>"); } else { Sb.Append("<size=34>").Append(VarkourLocalization.FormatTime(ElapsedMs())).Append("</size>"); } int num = course.Zones.Count - 1; int num2 = NextZoneIndex - 1; Sb.Append('\n').Append(VarkourLocalization.T("varkour_hud_next", num2, num)); Sb.Append(" ").Append(PbText(course)).Append('\n') .Append(RecordText(course)); if (_unrankedReason != null) { Sb.Append("\n<color=#FFB060>").Append(VarkourLocalization.T("varkour_hud_unranked", _unrankedReason)).Append("</color>"); } Sb.Append("\n<size=16>").Append(VarkourLocalization.T("varkour_hud_keys", VarkourInput.KeyName(VarkourConfig.RestartKey), VarkourInput.KeyName(VarkourConfig.CancelKey))); if (Practice) { Sb.Append(" ").Append(VarkourLocalization.T("varkour_hud_practice_key", VarkourInput.KeyName(VarkourConfig.PracticeRespawnKey))); } Sb.Append("</size>"); RunHud.SetMain(Sb.ToString()); } } private static void Finish(Course course, long totalMs) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) string text = _unrankedReason ?? RunRules.GetUnrankedReason(Player.m_localPlayer); List<long> splits = new List<long>(Splits); long timeMs; List<long> splits2; bool flag = ClientCourses.TryGetPersonalBest(course, out timeMs, out splits2); bool num = ClientCourses.IsDraft(course); RunFeedback.Finish(((Component)Player.m_localPlayer).transform.position); ShowResults(course, totalMs, splits, flag ? splits2 : null, text); ClearRun(); ModeMachine.ReturnToIdle(); RunHud.SetMain(null); if (num) { ClientCourses.RecordDraftRun(course, totalMs); if (text == null && course.AuthorId == ClientCourses.LocalPlayerId) { Notify.Center(VarkourLocalization.T("varkour_msg_publishing", course.Name)); VarkourNet.SendPublish(course, totalMs, splits); } else { string text2 = text ?? "not the author"; VarkourPlugin.Log.LogInfo((object)("Draft '" + course.Name + "' finished but not published: " + text2)); Notify.Center(VarkourLocalization.T("varkour_msg_draft_not_published", text2)); } ClientCourses.Changed(); } else if (text == null) { VarkourNet.SendSubmitRun(course, totalMs, splits); } } private static void ShowResults(Course course, long totalMs, List<long> splits, List<long> pbSplits, string reason) { Sb.Length = 0; Sb.Append("<size=22>").Append(course.Name).Append("</size>\n"); Sb.Append(CourseRecordText(course)).Append('\n'); Sb.Append(VarkourLocalization.T("varkour_hud_finished", VarkourLocalization.FormatTime(totalMs))); if (pbSplits != null && pbSplits.Count == splits.Count) { Sb.Append(" ").Append(VarkourLocalization.FormatDelta(totalMs - pbSplits[pbSplits.Count - 1])); } Sb.Append('\n'); if (reason != null) { Sb.Append("<color=#FFB060>").Append(VarkourLocalization.T("varkour_hud_unranked", reason)).Append("</color>\n"); } for (int i = 0; i < splits.Count; i++) { int index = i + 1; string text = ((course.Zones[index].Type == ZoneType.End) ? VarkourLocalization.T("varkour_label_end") : CourseEditor.CheckpointLabel(course.CheckpointNumberAt(index))); Sb.Append(VarkourLocalization.T("varkour_hud_split", text, VarkourLocalization.FormatTime(splits[i]))); if (pbSplits != null && pbSplits.Count == splits.Count) { Sb.Append(" ").Append(VarkourLocalization.FormatDelta(splits[i] - pbSplits[i])); } Sb.Append('\n'); } RunHud.ShowResults(Sb.ToString()); } private static void Cancel(string messageToken) { if (messageToken != null) { Notify.Center(VarkourLocalization.T(messageToken)); } ClearRun(); ModeMachine.ReturnToIdle(); RunHud.SetMain(null); } private static void ClearRun() { ActiveCourse = null; NextZoneIndex = -1; Splits.Clear(); _unrankedReason = null; _runCounter++; } private static string PbText(Course course) { if (!ClientCourses.TryGetPersonalBest(course, out var timeMs, out var _)) { return VarkourLocalization.T("varkour_hud_no_pb"); } return VarkourLocalization.T("varkour_hud_pb", VarkourLocalization.FormatTime(timeMs)); } private static string RecordText(Course course) { string text = CourseRecordText(course); if (ClientCourses.IsDraft(course)) { return text; } return text + " " + VarkourLocalization.T("varkour_hud_runs", course.RunCount); } private static string CourseRecordText(Course course) { LeaderboardView leaderboard = ClientCourses.GetLeaderboard(course.Id); if (leaderboard == null || leaderboard.Top.Count <= 0) { return VarkourLocalization.T("varkour_hud_no_record"); } return VarkourLocalization.T("varkour_hud_record", VarkourLocalization.FormatTime(leaderboard.Top[0].TimeMs), leaderboard.Top[0].PlayerName); } private static Course Refresh(Course course) { if (course == null) { return null; } return ClientCourses.GetPublished(course.Id) ?? ClientCourses.GetDraft(course.Id); } public static bool InZone(Zone zone, Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (zone == null) { return false; } float num = pos.y - zone.Position.y; if (num > VarkourConfig.ZoneHeightAbove.Value || num < 0f - VarkourConfig.ZoneDepthBelow.Value) { return false; } float num2 = ((zone.Type == ZoneType.Checkpoint) ? (zone.Radius + 0.3f) : zone.Radius); return HorizontalDistance(zone.Position, pos) <= num2; } private static float HorizontalDistance(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return Mathf.Sqrt(num * num + num2 * num2); } private static float HorizontalSpeed(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Vector3 velocity = ((Character)player).GetVelocity(); return Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z); } } internal static class RunHud { private static Text _main; private static Text _results; public static void SetMain(string text) { if (Ensure()) { bool flag = !string.IsNullOrEmpty(text); if (flag && _main.text != text) { _main.text = text; } if (((Component)_main).gameObject.activeSelf != flag) { ((Component)_main).gameObject.SetActive(flag); } } } public static void ShowResults(string text) { if (Ensure()) { _results.text = text; ((Component)_results).gameObject.SetActive(true); } } public static void HideResults() { if ((Object)(object)_results != (Object)null && ((Component)_results).gameObject.activeSelf) { ((Component)_results).gameObject.SetActive(false); } } public static void Tick() { bool flag = (Object)(object)Hud.instance != (Object)null && Hud.instance.IsVisible(); if ((Object)(object)_main != (Object)null && !flag && ((Component)_main).gameObject.activeSelf) { ((Component)_main).gameObject.SetActive(false); } if (!flag) { HideResults(); } } private static bool Ensure() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_main != (Object)null && (Object)(object)_results != (Object)null) { return true; } GameObject customGUIFront = GUIManager.CustomGUIFront; if ((Object)(object)customGUIFront == (Object)null) { return false; } GameObject obj = GUIManager.Instance.CreateText(string.Empty, customGUIFront.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -150f), GUIManager.Instance.AveriaSerifBold, 24, GUIManager.Instance.ValheimOrange, true, Color.black, 700f, 160f, false); ((Object)obj).name = "Varkour_HudMain"; _main = obj.GetComponent<Text>(); _main.alignment = (TextAnchor)1; _main.supportRichText = true; ((Graphic)_main).raycastTarget = false; obj.SetActive(false); GameObject obj2 = GUIManager.Instance.CreateText(string.Empty, customGUIFront.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-190f, 60f), GUIManager.Instance.AveriaSerifBold, 18, Color.white, true, Color.black, 340f, 520f, false); ((Object)obj2).name = "Varkour_HudResults"; _results = obj2.GetComponent<Text>(); _results.alignment = (TextAnchor)3; _results.supportRichText = true; ((Graphic)_results).raycastTarget = false; obj2.SetActive(false); return true; } } internal static class RunRules { public static string GetUnrankedReason(Player player) { if ((Object)(object)player == (Object)null) { return null; } if (RunController.Practice) { return VarkourLocalization.T("varkour_unranked_practice"); } if (player.InDebugFlyMode() || ((Character)player).IsDebugFlying()) { return VarkourLocalization.T("varkour_unranked_fly"); } if (((Character)player).InGodMode()) { return VarkourLocalization.T("varkour_unranked_god"); } if (player.NoCostCheat()) { return VarkourLocalization.T("varkour_unranked_nocost"); } return null; } } } namespace Varkour.Patches { [HarmonyPatch] internal static class HardcoreParkourPatch { private static bool Applies(Character character) { return HardcoreParkour.IsActive(character); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Player), "GetJogSpeedFactor")] private static void CapJogFactor(Player __instance, ref float __result) { if (Applies((Character)(object)__instance) && __result > 1f) { __result = 1f; } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Player), "GetRunSpeedFactor")] private static void CapRunFactor(Player __instance, ref float __result) { if (Applies((Character)(object)__instance) && __result > 1f) { __result = 1f; } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")] private static void RememberSpeed(ref float speed, out float __state) { __state = speed; } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")] private static void CapStatusEffectSpeed(ref float speed, float __state, Character ___m_character) { if (Applies(___m_character)) { speed = Mathf.Min(speed, __state); } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectJumpMods")] private static void RememberJump(ref Vector3 jump, out Vector3 __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) __state = jump; } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(SEMan), "ApplyStatusEffectJumpMods")] private static void CapJump(ref Vector3 jump, Vector3 __state, Character ___m_character) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (Applies(___m_character)) { if (jump.y > __state.y) { jump.y = __state.y; } float num = jump.x * jump.x + jump.z * jump.z; float num2 = __state.x * __state.x + __state.z * __state.z; if (num > num2 && num > 0f) { float num3 = Mathf.Sqrt(num2 / num); jump.x *= num3; jump.z *= num3; } } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] private static void RememberRegen(ref float staminaMultiplier, out float __state) { __state = staminaMultiplier; } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] private static void CapRegen(ref float staminaMultiplier, float __state, Character ___m_character) { if (Applies(___m_character)) { staminaMultiplier = Mathf.Min(staminaMultiplier, __state); } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(SEMan), "ModifyWalkVelocity")] private static void RememberVelocity(ref Vector3 vel, out Vector3 __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) __state = vel; } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(SEMan), "ModifyWalkVelocity")] private static void RestoreFallSpeed(ref Vector3 vel, Vector3 __state, Character ___m_character) { //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) if (Applies(___m_character) && __state.y < 0f && vel.y > __state.y) { vel.y = __state.y; } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(SEMan), "ModifyFallDamage")] private static void NoFallDamage(ref float damage, Character ___m_character) { if (Applies(___m_character)) { damage = 0f; } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] private static void SetParkourStamina(Player __instance, ref float stamina) { if (HardcoreParkour.TryGetMaxStamina((Character)(object)__instance, out var maxStamina)) { stamina = maxStamina; } } } [HarmonyPatch] internal static class PlacementPatch { [HarmonyPrefix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static bool TryPlacePiece(Player __instance, Piece piece, ref bool __result) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!MarkerPieces.TryGetZoneType(piece, out var type)) { return true; } __result = false; if (!IsEditingLocalPlayer(__instance)) { return false; } GameObject placementGhost = __instance.m_placementGhost; if ((Object)(object)placementGhost == (Object)null || !placementGhost.activeSelf) { ((Character)__instance).Message((MessageType)2, VarkourLocalization.T("varkour_msg_no_surface"), 0, (Sprite)null, false); return false; } CourseEditor.PlaceZone(type, placementGhost.transform.position); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "PlacePiece")] private static bool PlacePiece(Player __instance, Piece piece, Vector3 pos) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!MarkerPieces.TryGetZoneType(piece, out var type)) { return true; } if (IsEditingLocalPlayer(__instance)) { CourseEditor.PlaceZone(type, pos); } return false; } private static bool IsEditingLocalPlayer(Player player) { if (player == Player.m_localPlayer) { return ModeMachine.Current == VarkourMode.Editing; } return false; } } [HarmonyPatch] internal static class WindowInputPatch { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerController), "InInventoryEtc")] private static void StopMouseLook(ref bool __result) { if (VarkourWindow.CursorActive) { __result = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TakeInput")] private static void NoWorldActions(ref bool __result) { if (VarkourWindow.CursorActive) { __result = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static void FreeCursor() { if (VarkourWindow.CursorActive) { ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } } } namespace Varkour.Net { internal static class Packets { private const int MaxZonesOnWire = 1000; private const int MaxSplitsOnWire = 1000; private const int MaxCoursesOnWire = 100000; public static void WriteCourse(ZPackage pkg, Course c) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) pkg.Write(c.Id ?? string.Empty); pkg.Write(c.Name ?? string.Empty); pkg.Write(c.AuthorId); pkg.Write(c.AuthorName ?? string.Empty); pkg.Write(c.Version); pkg.Write(c.RunCount); pkg.Write(c.Zones.Count); foreach (Zone zone in c.Zones) { pkg.Write((int)zone.Type); pkg.Write(zone.Position); pkg.Write(zone.Radius); } } public static Course ReadCourse(ZPackage pkg) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Course course = new Course { Id = pkg.ReadString(), Name = pkg.ReadString(), AuthorId = pkg.ReadLong(), AuthorName = pkg.ReadString(), Version = pkg.ReadInt(), RunCount = pkg.ReadInt() }; int num = Bounded(pkg.ReadInt(), 1000); course.Zones = new List<Zone>(num); for (int i = 0; i < num; i++) { int num2 = pkg.ReadInt(); Vector3 position = pkg.ReadVector3(); float radius = pkg.ReadSingle(); course.Zones.Add(new Zone { Type = (ZoneType)Mathf.Clamp(num2, 0, 2), Position = position, Radius = radius }); } return course; } public static void WriteCourses(ZPackage pkg, List<Course> courses) { pkg.Write(courses.Count); foreach (Course course in courses) { WriteCourse(pkg, course); } } public static List<Course> ReadCourses(ZPackage pkg) { int num = Bounded(pkg.ReadInt(), 100000); List<Course> list = new List<Course>(num); for (int i = 0; i < num; i++) { list.Add(ReadCourse(pkg)); } return list; } public static void WriteSplits(ZPackage pkg, List<long> splits) { pkg.Write(splits.Count); foreach (long split in splits) { pkg.Write(split); } } public static List<long> ReadSplits(ZPackage pkg) { int num = Bounded(pkg.ReadInt(), 1000); List<long> list = new List<long>(num); for (int i = 0; i < num; i++) { list.Add(pkg.ReadLong()); } return list; } public static void WriteRecord(ZPackage pkg, RunRecord r) { pkg.Write(r.CourseId ?? string.Empty); pkg.Write(r.CourseVersion); pkg.Write(r.PlayerId); pkg.Write(r.PlayerName ?? string.Empty); pkg.Write(r.TimeMs); pkg.Write(r.SetUtc ?? string.Empty); WriteSplits(pkg, r.SplitsMs ?? new List<long>()); } public static RunRecord ReadRecord(ZPackage pkg) { return new RunRecord { CourseId = pkg.ReadString(), CourseVersion = pkg.ReadInt(), PlayerId = pkg.ReadLong(), PlayerName = pkg.ReadString(), TimeMs = pkg.ReadLong(), SetUtc = pkg.ReadString(), SplitsMs = ReadSplits(pkg) }; } private static int Bounded(int value, int max) { if (value < 0 || value > max) { throw new InvalidDataException($"Count {value} out of range (max {max})."); } return value; } } internal struct CourseLimits { public int MaxNameLength; public int MaxZones; public float MinRadius; public float MaxRadius; } internal static class ServerRules { public const int MaxIdLength = 64; public static string ValidateCourse(Course c, CourseLimits limits) { if (c == null || string.IsNullOrEmpty(c.Id) || c.Id.Length > 64) { return "bad id"; } string text = c.Name?.Trim(); if (string.IsNullOrEmpty(text) || text.Length > limits.MaxNameLength || !CourseName.IsClean(text)) { return "bad name"; } if (c.Zones == null || c.Zones.Count < 2 || c.Zones.Count > limits.MaxZones) { return "zone count"; } float num = Math.Min(limits.MinRadius, limits.MaxRadius) - 0.001f; float num2 = Math.Max(limits.MinRadius, limits.MaxRadius) + 0.001f; int num3 = 0; int num4 = 0; foreach (Zone zone in c.Zones) { if (zone.Type == ZoneType.Start) { num3++; } else if (zone.Type == ZoneType.End) { num4++; } if (!IsFinite(zone.Radius) || zone.Radius < num || zone.Radius > num2) { return "zone radius"; } if (!IsFinite(zone.Position.x) || !IsFinite(zone.Position.y) || !IsFinite(zone.Position.z)) { return "zone position"; } } if (num3 != 1 || num4 != 1 || c.Zones[0].Type != ZoneType.Start || c.Zones[c.Zones.Count - 1].Type != ZoneType.End) { return "needs exactly one Start (first) and one End (last)"; } return null; } public static string ValidateRun(Course course, long timeMs, List<long> splits) { if (timeMs <= 0) { return "time must be > 0"; } if (splits == null || splits.Count != course.Zones.Count - 1) { return "split count mismatch"; } long num = -1L; foreach (long split in splits) { if (split <= num) { return "splits must be strictly increasing"; } num = split; } if (splits[splits.Count - 1] != timeMs) { return "last split must equal total time"; } return null; } public static bool MayPublish(Course course, Course existing, long playerId, bool admin) { if (admin) { return true; } if (course.AuthorId == playerId) { if (existing != null) { return existing.AuthorId == playerId; } return true; } return false; } public static bool MayRemove(Course existing, long playerId, bool admin) { if (!admin) { return existing.AuthorId == playerId; } return true; } private static bool IsFinite(float f) { if (!float.IsNaN(f)) { return !float.IsInfinity(f); } return false; } } internal static class ServerStore { public struct SubmitResult { public bool Accepted; public int Rank; public long RecordMs; } private const string FileName = "server.json"; private static VarkourServerData _data; private static string _world; private static string _path; private static readonly List<RunRecord> Scratch = new List<RunRecord>(); public static bool Loaded => _data != null; public static string WorldName => _world; public static List<Course> Courses => _data?.Courses ?? new List<Course>(); public static CourseLimits Limits => new CourseLimits { MaxNameLength = VarkourConfig.MaxCourseNameLength.Value, MaxZones = VarkourConfig.MaxZonesPerCourse.Value, MinRadius = VarkourConfig.MinZoneRadius.Value, MaxRadius = VarkourConfig.MaxZoneRadius.Value }; public static void Tick() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { if (_data != null) { Unload(); } } else if (instance.IsServer()) { string worldName = instance.GetWorldName(); if (!string.IsNullOrEmpty(worldName) && worldName != _world) { Load(worldName); } } } private static void Load(string world) { _world = world; _path = Path.Combine(JsonStore.WorldFolder(world), "server.json"); _data = JsonStore.LoadServer(_path); if (_data == null) { VarkourPlugin.Log.LogError((object)("Server store for '" + world + "' is NOT loaded. Fix or remove " + _path + " and reload the world.")); return; } _data.WorldName = world; _data.Courses = _data.Courses ?? new List<Course>(); _data.Records = _data.Records ?? new List<RunRecord>(); _data.Courses.RemoveAll((Course c) => c == null || string.IsNullOrEmpty(c.Id)); VarkourPlugin.Log.LogInfo((object)$"Server store loaded for '{world}' from {_path}: {_data.Courses.Count} course(s), {_data.Records.Count} record(s)."); VarkourNet.BroadcastFullSync(); } public static void Unload() { if (_data != null) { Save(); } _data = null; _world = null; _path = null; } private static void Save() { if (_data != null && _path != null) { JsonStore.Save(_path, _data); } } public static Course Get(string id) { if (_data == null || id == null) { return null; } foreach (Course course in _data.Courses) { if (course.Id == id) { return course; } } return null; } public static void Publish(Course course, RunRecord firstRun) { if (_data != null) { course.Name = course.Name.Trim(); course.RunCount = 1; _data.Courses.RemoveAll((Course c) => c.Id == course.Id); _data.Courses.Add(course); _data.Records.RemoveAll((RunRecord r) => r.CourseId == course.Id); _data.Records.Add(firstRun); Save(); } } public static Course Remove(string id) { Course course = Get(id); if (course == null) { return null; } _data.Courses.Remove(course); _data.Records.RemoveAll((RunRecord r) => r.CourseId == id); Save(); return course; } public static void GetBoard(string courseId, List<RunRecord> into) { into.Clear(); if (_data == null) { return; } foreach (RunRecord record in _data.Records) { if (record.CourseId == courseId) { into.Add(record); } } into.Sort(CompareRecords); } public static SubmitResult Submit(RunRecord record) { Course course = Get(record.CourseId); if (course != null) { course.RunCount++; } GetBoard(record.CourseId, Scratch); RunRecord runRecord = Scratch.Find((RunRecord r) => r.PlayerId == record.PlayerId); SubmitResult result = default(SubmitResult); if (runRecord != null && runRecord.TimeMs <= record.TimeMs) { result.Rank = Scratch.IndexOf(runRecord) + 1; result.RecordMs = Scratch[0].TimeMs; Save(); return result; } if (runRecord != null) { _data.Records.Remove(runRecord); Scratch.Remove(runRecord); } _data.Records.Add(record); Scratch.Add(record); Scratch.Sort(CompareRecords); int value = VarkourConfig.LeaderboardSize.Value; for (int num = Scratch.Count - 1; num >= value; num--) { _data.Records.Remove(Scratch[num]); Scratch.RemoveAt(num); } result.Accepted = true; result.Rank = Scratch.IndexOf(record) + 1; result.RecordMs = Scratch[0].TimeMs; Save(); return result; } public static string NowUtc() { return DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); } private static int CompareRecords(RunRecord a, RunRecord b) { int num = a.TimeMs.CompareTo(b.TimeMs); if (num == 0) { return string.CompareOrdinal(a.SetUtc, b.SetUtc); } return num; } } internal static class VarkourNet { private enum RemoveReason : byte { Unpublish, Delete } private const byte SyncFull = 0; private const byte SyncUpsert = 1; private const byte SyncRemove = 2; private static CustomRPC _courseSyncRequest; private static CustomRPC _courseSync; private static CustomRPC _publish; private static CustomRPC _removeCourse; private static CustomRPC _submitRun; private static CustomRPC _requestLeaderboard; private static CustomRPC _leaderboardData; private static CustomRPC _newRecord; private static CustomRPC _serverNotice; private static readonly List<RunRecord> Board = new List<RunRecord>(); private static long OwnId => ZDOMan.GetSessionID(); private static long ServerId { get { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return 0L; } if (instance.IsServer()) { return OwnId; } return instance.GetServerPeer()?.m_uid ?? 0; } } public static void Register() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0062: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0090: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00be: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ec: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_011a: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0148: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0176: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01a3: Expected O, but got Unknown NetworkManager instance = NetworkManager.Instance; string text = "Varkour_"; _courseSyncRequest = instance.AddRPC(text + "CourseSyncRequest", new CoroutineHandler(OnCourseSyncRequest), new CoroutineHandler(Ignore)); _courseSync = instance.AddRPC(text + "CourseSync", new CoroutineHandler(OnCourseSync), new CoroutineHandler(OnCourseSync)); _publish = instance.AddRPC(text + "PublishCourse", new CoroutineHandler(OnPublish), new CoroutineHandler(Ignore)); _removeCourse = instance.AddRPC(text + "RemoveCourse", new CoroutineHandler(OnRemoveCourse), new CoroutineHandler(Ignore)); _submitRun = instance.AddRPC(text + "SubmitRun", new CoroutineHandler(OnSubmitRun), new CoroutineHandler(Ignore)); _requestLeaderboard = instance.AddRPC(text + "RequestLeaderboard", new CoroutineHandler(OnRequestLeaderboard), new CoroutineHandler(Ignore)); _leaderboardData = instance.AddRPC(text + "LeaderboardData", new CoroutineHandler(OnLeaderboardData), new CoroutineHandler(OnLeaderboardData)); _newRecord = instance.AddRPC(text + "NewRecord", new CoroutineHandler(OnNewRecord), new CoroutineHandler(OnNewRecord)); _serverNotice = instance.AddRPC(text + "ServerNotice", new CoroutineHandler(OnServerNotice), new CoroutineHandler(OnServerNotice)); } private static bool SendToServer(CustomRPC rpc, ZPackage pkg, bool notifyIfOffline = true) { long serverId = ServerId; if (serverId == 0L || ZRoutedRpc.instance == null) { if (notifyIfOffline) { Notify.Center(VarkourLocalization.T("varkour_msg_server_offline")); } return false; } rpc.SendPackage(serverId, pkg); return true; } private static bool FromServer(long sender) { if (GUIManager.IsHeadless()) { return false; } return sender == ServerId; } private static bool TryIdentify(long sender, out long playerId, out string playerName) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) playerId = 0L; playerName = null; ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return false; } if (sender == OwnId && !instance.IsDedicated()) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } playerId = localPlayer.GetPlayerID(); playerName = localPlayer.GetPlayerName(); return playerId != 0; } ZNetPeer peer = instance.GetPeer(sender); if (peer == null || peer.m_characterID == ZDOID.None) { return false; } ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(peer.m_characterID) : null); if (val == null) { return false; } playerId = val.GetLong(ZDOVars.s_playerID, 0L); playerName = (string.IsNullOrEmpty(peer.m_playerName) ? val.GetString(ZDOVars.s_playerName, "?") : peer.m_playerName); return playerId != 0; } private static bool Identify(long sender, long claimedId, string claimedName, out long playerId, out string playerName) { if (!TryIdentify(sender, out playerId, out playerName)) { Notice(sender, "varkour_err_no_identity", string.Empty); return false; } if (claimedId != playerId || (claimedName != null && claimedName != playerName)) { VarkourPlugin.Log.LogWarning((object)$"Peer {sender} ({playerName}, id {playerId}) sent a packet claiming to be {claimedName} (id {claimedId}); using the server's view."); } return true; } private static bool IsAdmin(long sender) { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return false; } if (sender == OwnId && !instance.IsDedicated()) { return true; } return ZNetExtension.IsAdmin(instance, sender); } private static void Broadcast(CustomRPC rpc, ZPackage pkg) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null)) { byte[] array = pkg.GetArray(); List<ZNetPeer> peers = instance.GetPeers(); if (peers != null && peers.Count > 0) { rpc.SendPackage(new List<ZNetPeer>(peers), new ZPackage(array)); } if (!instance.IsDedicated()) { rpc.SendPackage(OwnId, new ZPackage(array)); } } } private static IEnumerator Ignore(long sender, ZPackage pkg) { yield break; } public static bool RequestCourseSync() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown return SendToServer(_courseSyncRequest, new ZPackage(), notifyIfOffline: false); } public static void SendPublish(Course course, long timeMs, List<long> splits) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(ClientCourses.LocalPlayerId); val.Write(ClientCourses.LocalPlayerName); Packets.WriteCourse(val, course); val.Write(timeMs); Packets.WriteSplits(val, splits); VarkourPlugin.LogVerbose($"Sending PublishCourse '{course.Name}' to server {ServerId} (own {OwnId})."); SendToServer(_publish, val); } public static void SendUnpublish(string courseId) { SendRemove(courseId, RemoveReason.Unpublish); } public static void SendDelete(string courseId) { SendRemove(courseId, RemoveReason.Delete); } private static void SendRemove(string courseId, RemoveReason reason) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Un