Decompiled source of Pro Golf Plus v0.1.43
BepInEx\plugins\ProGolfMod.dll
Decompiled a month 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using Steamworks; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ProGolfMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ProGolfMod")] [assembly: AssemblyTitle("ProGolfMod")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ProGolfMod { [BepInPlugin("codex.superbattlegolf.progolfplus", "Pro Golf Plus", "0.1.43")] public sealed class ProGolfPlugin : BaseUnityPlugin { private sealed class DriveCandidate { public PlayerInfo Player; public ulong PlayerGuid; public Vector3 StartPosition; } private sealed class FirstDriveResult { public string PlayerName; public float Distance; public bool IsValid; } private sealed class ClosestToPinResult { public string PlayerName; public float Distance; public bool IsValid; } private sealed class CartFlipState { public WheelCollider[] Wheels = Array.Empty<WheelCollider>(); public bool WasUprightOnWheels; public bool FlipInProgress; public int CurrentFlipStreak; public float AccumulatedFlipRadians; public float LastFlipPollTime = -1f; public float SettledSince = -1f; public ulong ResponsiblePlayerGuid; public string ResponsiblePlayerName; } [HarmonyPatch(typeof(CourseManager), "BeginCountdownToMatchEnd")] private static class SkipFirstFinishCountdownPatch { private static bool Prefix(CourseManager __instance) { if (!IsProGolfScoringActive() || (Object)(object)__instance == (Object)null) { return true; } if (ShouldBlockNativeEndCountdown(__instance)) { return false; } if (AllActivePlayersResolved(__instance)) { TryAnnounceClosestToPinIfReady(); TryAnnounceHoleStatsIfReady(); return true; } ProGolfPlugin instance = ProGolfPlugin.instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)"Skipped Pro Golf end-of-hole countdown because active players are still playing."); } return false; } } [HarmonyPatch(typeof(CourseManager), "CountDownToMatchEndRoutine")] private static class SkipMatchEndCountdownRoutinePatch { private static bool Prefix(CourseManager __instance, ref IEnumerator __result) { if (ShouldBlockNativeEndCountdown(__instance)) { __result = EmptyReadyUpHoldRoutine(); return false; } return true; } } [HarmonyPatch(typeof(CourseManager), "OnMatchStateChanged")] private static class HoldReadyUpMatchStatePatch { private static bool Prefix(CourseManager __instance, MatchState previousState, MatchState currentState) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (suppressReadyMatchStateRollback || (int)currentState != 4 || !ShouldBlockNativeEndCountdown(__instance)) { return true; } RollBackReadyUpMatchState(__instance, (MatchState)(((int)previousState == 4) ? 3 : ((int)previousState))); return false; } } [HarmonyPatch(typeof(CourseManager), "set_NetworkmatchState")] private static class BlockReadyUpMatchStateSetterPatch { private static bool Prefix(CourseManager __instance, ref MatchState value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown MatchState replacementState = value; if (!TryBlockReadyUpMatchStateChange(__instance, value, ref replacementState)) { return true; } value = (MatchState)(int)replacementState; return true; } } [HarmonyPatch(typeof(CourseManager), "ServerStartNextMatch")] private static class BlockReadyUpNextMatchPatch { private static bool Prefix(CourseManager __instance) { if (!ShouldBlockNextMatchForReadyUp(__instance)) { return true; } return false; } } [HarmonyPatch(typeof(MatchEndCountdown), "Show")] private static class SuppressReadyCountdownShowPatch { private static bool Prefix() { return !ShouldSuppressReadyCountdownUi(); } } [HarmonyPatch(typeof(MatchEndCountdown), "SetTime")] private static class SuppressReadyCountdownSetTimePatch { private static bool Prefix() { if (!ShouldSuppressReadyCountdownUi()) { return true; } MatchEndCountdown.Hide(); return false; } } [HarmonyPatch(typeof(MatchEndCountdown), "EnterOvertime")] private static class SuppressReadyCountdownOvertimePatch { private static bool Prefix() { if (!ShouldSuppressReadyCountdownUi()) { return true; } MatchEndCountdown.Hide(); return false; } } [HarmonyPatch(typeof(CourseManager), "OnPlayerStatesChanged")] private static class AnnounceHoleStatsOnPlayerStateChangedPatch { private static void Postfix(CourseManager __instance) { if (!((Object)(object)__instance == (Object)null) && NetworkServer.active && IsProGolfScoringActive() && AllActivePlayersResolved(__instance)) { TryAnnounceClosestToPinIfReady(); TryAnnounceHoleStatsIfReady(); OpenReadyGateForCurrentHole(); } } } [HarmonyPatch(typeof(PlayerState), "CompareTo")] private static class ProGolfStrokeFirstPlayerStateSortPatch { private static bool Prefix(PlayerState __instance, PlayerState other, ref int __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return !TryCompareProGolfPlayerStates(__instance, other, ref __result); } } [HarmonyPatch(typeof(ScoreboardEntry), "PopulateWith")] private static class ProGolfScoreboardEntryStatsPatch { private static void Postfix(ScoreboardEntry __instance, PlayerState playerState) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) UpdateScoreboardEntryProGolfStats(__instance, playerState); } } [HarmonyPatch(typeof(Scoreboard), "Show")] private static class OpenReadyGateOnScoreboardShowPatch { private static void Postfix() { if (NetworkServer.active && IsReadyScoreboardWindowActive()) { OpenReadyGateForCurrentHole(); } } } [HarmonyPatch(typeof(Scoreboard), "Refresh")] private static class ProGolfScoreboardStatCardPatch { private static void Postfix(Scoreboard __instance) { UpdateScoreboardProGolfStatCard(__instance); } } [HarmonyPatch(typeof(PlayerGolfer), "InformScored")] private static class CaptureClosestToPinOnScorePatch { private static void Prefix(PlayerGolfer __instance) { CaptureClosestToPinOnScore(__instance); } } [HarmonyPatch(typeof(CourseManager), "TryPlayHoleMusic")] private static class ForceNormalHoleMusicPatch { private static void Prefix(ref bool hurryUpInstantly) { if (IsActiveProGolf()) { hurryUpInstantly = false; } } } [HarmonyPatch(typeof(CourseManager), "HurryUpHoleMusic")] private static class PreventHurryUpMusicPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(GolfBall), "OnWillApplyGolfSwingHitPhysics")] private static class BeginLongestDriveTrackingPatch { private static void Prefix(GolfBall __instance) { BeginDriveTracking(__instance); } } [HarmonyPatch(typeof(PlayerGolfer), "OnPlayerHitOwnBall")] private static class TrackPerfectShotPatch { private static void Postfix(PlayerGolfer __instance) { TrackPerfectShot(__instance); } } [HarmonyPatch(typeof(GolfBall), "set_IsStationary")] private static class CompleteLongestDriveTrackingPatch { private static void Postfix(GolfBall __instance, bool value) { if (value) { TryCompleteDriveTracking(__instance); TryCaptureClosestToPinFromStationaryBall(__instance); } } } [HarmonyPatch(typeof(CourseManager), "AddPenaltyStroke")] private static class InvalidatePenaltyDrivePatch { private static void Prefix(PlayerGolfer penalizedPlayer) { InvalidateFirstDrive((penalizedPlayer != null) ? penalizedPlayer.PlayerInfo : null); } } [HarmonyPatch(typeof(PlayerGolfer), "ServerEliminate")] private static class HazardEliminationRespawnPatch { private static bool Prefix(PlayerGolfer __instance, EliminationReason immediateEliminationReason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (TryRespawnHazardEliminationAtBall(__instance, immediateEliminationReason)) { return false; } MarkBallRespawnForHazardElimination(__instance, immediateEliminationReason); return true; } } [HarmonyPatch(typeof(PlayerMovement), "TryBeginRespawn")] private static class BeginRespawnAtBallPatch { private static void Prefix(PlayerMovement __instance, ref RespawnTarget respawnTarget) { RedirectHazardRespawnToBall(__instance, ref respawnTarget); } } [HarmonyPatch(typeof(PlayerMovement), "CmdPlayOutOfBoundsEliminationExplosionForAllClients")] private static class SuppressPlayerOutOfBoundsExplosionCommandPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(PlayerMovement), "RpcPlayOutOfBoundsEliminationExplosion")] private static class SuppressPlayerOutOfBoundsExplosionRpcPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(PlayerMovement), "PlayOutOfBoundsEliminationExplosionInternal")] private static class SuppressPlayerOutOfBoundsExplosionPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(GolfCartInfo), "ServerPlayOutOfBoundsEliminationExplosionForAllClients")] private static class SuppressCartOutOfBoundsExplosionServerPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(GolfCartInfo), "RpcPlayOutOfBoundsEliminationExplosion")] private static class SuppressCartOutOfBoundsExplosionRpcPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(GolfCartInfo), "PlayOutOfBoundsEliminationExplosionInternal")] private static class SuppressCartOutOfBoundsExplosionPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(PlayerGolfer), "CanMove")] private static class AllowMovementAfterHoleOutPatch { private static void Postfix(PlayerGolfer __instance, ref bool __result) { if (IsActiveProGolf() && HasPlayerScoredThisHole(__instance)) { __result = true; } } } [HarmonyPatch(typeof(GolfHole), "ServerOnBallScored")] private static class SuppressHoleOutScoreBlastPatch { private static bool Prefix() { return !IsActiveProGolf(); } } [HarmonyPatch(typeof(PlayerInfo), "RpcPopUpPlacementScore")] private static class SuppressPlacementScorePopupPatch { private static bool Prefix(PlayerInfo __instance) { if (!IsActiveProGolf()) { return true; } ShowProGolfHoleOutPopup(__instance); return false; } } [HarmonyPatch] private static class SuppressPlacementScorePopupUserCodePatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(PlayerInfo), "UserCode_RpcPopUpPlacementScore__Int32__Int32", (Type[])null, (Type[])null); } private static bool Prefix(PlayerInfo __instance) { if (!IsActiveProGolf()) { return true; } ShowProGolfHoleOutPopup(__instance); return false; } } [HarmonyPatch(typeof(PlayerInfo), "RpcPopUp")] private static class SuppressScorePopupPatch { private static bool Prefix(PlayerTextPopupType popupType) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (IsActiveProGolf()) { return !IsProGolfScorePopupType(popupType); } return true; } } [HarmonyPatch] private static class SuppressScorePopupUserCodePatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(PlayerInfo), "UserCode_RpcPopUp__PlayerTextPopupType__Int32", (Type[])null, (Type[])null); } private static bool Prefix(PlayerInfo __instance, PlayerTextPopupType popupType) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!IsActiveProGolf() || !IsProGolfScorePopupType(popupType)) { return true; } if (HasPlayerScoredThisHole((__instance != null) ? __instance.AsGolfer : null)) { ShowProGolfHoleOutPopup(__instance); } return false; } } [HarmonyPatch(typeof(PlayerInfo), "PopUpInternal")] private static class SuppressNativePlayerPopupInternalPatch { private static bool Prefix(PlayerInfo __instance) { if (!IsActiveProGolf() || isShowingProGolfHoleOutPopup) { return true; } if (HasPlayerScoredThisHole((__instance != null) ? __instance.AsGolfer : null)) { ShowProGolfHoleOutPopup(__instance); } return false; } } [HarmonyPatch(typeof(Checkpoint), "Awake")] private static class HideCheckpointOnAwakePatch { private static void Postfix(Checkpoint __instance) { if (IsActiveProGolf()) { SuppressCheckpointVisuals(__instance); } } } [HarmonyPatch(typeof(PlayerInventorySettings), "get_MaxItems")] private static class MinimumProGolfInventoryPatch { private static void Postfix(ref int __result) { if (IsActiveProGolf()) { __result = 3; } } } [HarmonyPatch(typeof(PlayerInventory), "OnStartServer")] private static class ServerStartLoadoutPatch { private static void Postfix(PlayerInventory __instance) { EnsureProGolfLoadout(__instance); } } [HarmonyPatch(typeof(PlayerInventory), "OnStartLocalPlayer")] private static class LocalStartLoadoutPatch { private static void Postfix(PlayerInventory __instance) { EnsureProGolfLoadout(__instance); } } [HarmonyPatch(typeof(PlayerInventory), "ServerTryAddItem")] private static class ProGolfItemGrantPatch { private static bool Prefix(PlayerInventory __instance, ItemType itemToAdd, ref bool __result) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if (!IsActiveProGolf() || !NetworkServer.active) { return true; } EnsureProGolfLoadout(__instance); if ((int)itemToAdd == 6 || (int)itemToAdd == 1 || (int)itemToAdd == 5) { __result = true; return false; } __result = false; return false; } } [HarmonyPatch(typeof(ItemPool), "GetWeightedRandomItem")] private static class RemovePermanentItemsFromItemPoolsPatch { private static bool Prefix(ItemPool __instance, ref ItemType __result) { if (!IsActiveProGolf()) { return true; } return !TryGetWeightedRandomAllowedPickupItem(__instance, out __result); } } [HarmonyPatch(typeof(ItemSpawner), "OnStartServer")] private static class HideInitialItemSpawnersPatch { private static void Postfix(ItemSpawner __instance) { if (IsActiveProGolf() && (Object)(object)__instance != (Object)null) { SuppressItemSpawner(__instance); } } } [HarmonyPatch(typeof(ItemSpawner), "ServerSpawnItemBox")] private static class PreventItemSpawnerRespawnsPatch { private static bool Prefix(ItemSpawner __instance) { if (!IsActiveProGolf()) { return true; } if ((Object)(object)__instance != (Object)null) { SuppressItemSpawner(__instance); } return false; } } [HarmonyPatch(typeof(PlayerInventory), "DecrementUseFromSlotAt")] private static class KeepPermanentItemsLoadedPatch { private static bool Prefix(PlayerInventory __instance, int index) { return !IsReservedPermanentSlot(__instance, index); } } [HarmonyPatch(typeof(PlayerInventory), "RemoveIfOutOfUses")] private static class PreventPermanentItemsRemovalPatch { private static bool Prefix(PlayerInventory __instance, int index) { return !IsReservedPermanentSlot(__instance, index); } } [HarmonyPatch(typeof(PlayerInventory), "DropItem")] private static class PreventDroppingPermanentItemsPatch { private static bool Prefix(PlayerInventory __instance) { return !IsReservedPermanentSlot(__instance, __instance.EquippedItemIndex); } } private const string PluginGuid = "codex.superbattlegolf.progolfplus"; private const string PluginName = "Pro Golf Plus"; private const string PluginVersion = "0.1.43"; private const string LobbyMemberVersionKey = "codex_progolfplus_member_version"; private const string LobbyRequiredVersionKey = "codex_progolfplus_required_version"; private const string LobbyActiveStateKey = "codex_progolfplus_active"; private const string LobbyActiveVersionKey = "codex_progolfplus_active_version"; private const string LobbyAnnouncementTextKey = "codex_progolfplus_announcement_text"; private const string LobbyAnnouncementVersionKey = "codex_progolfplus_announcement_version"; private const string LobbyHoleStatsPayloadKey = "codex_progolfplus_hole_stats_payload"; private const string LobbyHoleStatsVersionKey = "codex_progolfplus_hole_stats_version"; private const string LobbyReadyHoleKey = "codex_progolfplus_ready_hole"; private const string LobbyReadyGateHoleKey = "codex_progolfplus_ready_gate_hole"; private const string LobbyReadyGateVersionKey = "codex_progolfplus_ready_gate_version"; private const float LobbyPollInterval = 1f; private const float LocalMemberVersionPublishInterval = 2f; private const int ReservedCartSlotIndex = 0; private const int ReservedCoffeeSlotIndex = 1; private const int ReservedSpringBootsSlotIndex = 2; private const int TotalInventorySlots = 3; private const float CartFlipPollInterval = 0.25f; private const float CartDiscoveryPollInterval = 1f; private const float CartUprightDotThreshold = 0.65f; private const float CartMovingSpeedThreshold = 0.35f; private const float CartMovingAngularThreshold = 0.35f; private const float CartFlipStartAngularThreshold = 1f; private const float CartFlipFullRotationRadians = (float)Math.PI * 2f; private const float CartSettledSeconds = 0.5f; private const float ClosestToPinRadiusMeters = 9.144f; private static ProGolfPlugin instance; private static FieldInfo inventorySlotsField; private static FieldInfo itemPoolSpawnChancesField; private static FieldInfo itemSpawnerVisualsField; private static FieldInfo itemSpawnerPickupColliderField; private static FieldInfo itemSpawnerVisualsFillingObjectField; private static FieldInfo itemSpawnerVisualsIdleObjectField; private static FieldInfo itemSpawnerVisualsFillRendererField; private static FieldInfo itemSpawnerVisualsAnimatorField; private static FieldInfo checkpointVisualCenterField; private static FieldInfo checkpointBaseMeshField; private static FieldInfo checkpointScreenMeshField; private static FieldInfo checkpointAnimatorField; private static FieldInfo scoreboardEntryStatsBackgroundField; private static FieldInfo scoreboardEntryNameField; private static FieldInfo scoreboardEntryParentField; private static FieldInfo scoreboardBestHoleScoreStatField; private static FieldInfo scoreboardLongestChipInStatField; private static FieldInfo scoreboardItemPickupsStatField; private static FieldInfo scoreboardKnockoutRatioStatField; private static FieldInfo scoreboardStatLabelField; private static FieldInfo golfBallIsInHoleField; private static MethodInfo scoreboardMarkDirtyMethod; private static MethodInfo playerPopUpTextMethod; private static bool isShowingProGolfHoleOutPopup; private static bool allLobbyMembersCompatible = true; private static string incompatibleLobbyMembers = string.Empty; private static float nextLobbyPollTime; private static float nextLocalMemberVersionPublishTime; private static float nextCompatibilityWarningTime; private static bool lastPublishedActiveState; private static string lastObservedActiveVersion = string.Empty; private static bool hasObservedActiveState; private static bool lastObservedActiveState; private static string lastObservedHoleStatsVersion = string.Empty; private static string lastObservedReadyGateVersion = string.Empty; private static int observedReadyGateHoleIndex = int.MinValue; private static readonly Dictionary<GolfBall, DriveCandidate> activeDrives = new Dictionary<GolfBall, DriveCandidate>(); private static readonly Dictionary<ulong, FirstDriveResult> firstDriveResults = new Dictionary<ulong, FirstDriveResult>(); private static readonly Dictionary<ulong, ClosestToPinResult> closestToPinResults = new Dictionary<ulong, ClosestToPinResult>(); private static readonly Dictionary<ulong, int> perfectShotCounts = new Dictionary<ulong, int>(); private static readonly Dictionary<ulong, int> cartBestFlipStreaks = new Dictionary<ulong, int>(); private static readonly Dictionary<ulong, string> scoreboardRowRelativeScoreTexts = new Dictionary<ulong, string>(); private static readonly Dictionary<int, int> parByHoleIndex = new Dictionary<int, int>(); private static readonly Dictionary<ulong, float> holeStatsLongestDriveDistances = new Dictionary<ulong, float>(); private static readonly Dictionary<ulong, float> holeStatsClosestToPinDistances = new Dictionary<ulong, float>(); private static readonly Dictionary<ulong, float> holeStatsChipInDistances = new Dictionary<ulong, float>(); private static readonly HashSet<ulong> holeOutPopupsShown = new HashSet<ulong>(); private static readonly Dictionary<GolfCartMovement, CartFlipState> cartFlipStates = new Dictionary<GolfCartMovement, CartFlipState>(); private static readonly HashSet<PlayerMovement> forceNextRespawnAtBall = new HashSet<PlayerMovement>(); private static readonly HashSet<ItemSpawner> suppressedItemSpawners = new HashSet<ItemSpawner>(); private static readonly HashSet<Checkpoint> suppressedCheckpoints = new HashSet<Checkpoint>(); private static readonly List<GolfCartMovement> cachedCarts = new List<GolfCartMovement>(); private static readonly List<GolfCartMovement> staleCarts = new List<GolfCartMovement>(); private static int longestDriveHoleIndex = int.MinValue; private static bool longestDriveAnnounced; private static bool closestToPinAnnounced; private static bool holeStatsAnnounced; private static string lastObservedAnnouncementVersion = string.Empty; private static string topAnnouncementText = string.Empty; private static string topAnnouncementDetailText = string.Empty; private static float topAnnouncementVisibleUntil; private static float nextCartFlipPollTime; private static float nextCartDiscoveryPollTime; private static GUIStyle topAnnouncementBoxStyle; private static GUIStyle topAnnouncementTextStyle; private static GUIStyle topAnnouncementDetailStyle; private static GUIStyle readyUpBoxStyle; private static GUIStyle readyUpHeaderStyle; private static GUIStyle readyUpRowStyle; private static GUIStyle readyUpPromptStyle; private static Texture2D topAnnouncementBoxTexture; private static Texture2D readyUpBoxTexture; private static Texture2D proGolfCardHeaderTexture; private static Texture2D proGolfCardBandTexture; private static Texture2D proGolfReadyFlagTexture; private static Sprite proGolfCardHeaderSprite; private static Sprite proGolfCardBandSprite; private static Sprite proGolfReadyFlagSprite; private static readonly Dictionary<ScoreboardEntry, TextMeshProUGUI> scoreboardEntryStatLabels = new Dictionary<ScoreboardEntry, TextMeshProUGUI>(); private static readonly Dictionary<ScoreboardEntry, GameObject> scoreboardEntryReadyIndicators = new Dictionary<ScoreboardEntry, GameObject>(); private static readonly Dictionary<Scoreboard, GameObject> scoreboardAllPlayerStatsPanels = new Dictionary<Scoreboard, GameObject>(); private static readonly Dictionary<Scoreboard, GameObject> scoreboardReadyUpPanels = new Dictionary<Scoreboard, GameObject>(); private static int readyGateHoleIndex = int.MinValue; private static int readyGateCountdownTriggeredHoleIndex = int.MinValue; private static int localReadyHoleIndex = int.MinValue; private static int lastParTrackedHoleIndex = int.MinValue; private static float nextReadyGateLogTime; private static float nextReadyScoreboardRefreshTime; private static float nextReadyStateBlockLogTime; private static bool suppressReadyMatchStateRollback; private Harmony harmony; private ConfigEntry<bool> enabledConfig; private ConfigEntry<bool> readyUpBetweenHolesConfig; private ConfigEntry<float> grantCheckIntervalConfig; private ConfigEntry<float> longestDriveMinimumMetersConfig; private float nextGrantCheckTime; private void Awake() { //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Expected O, but got Unknown instance = this; enabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Pro Golf Plus."); readyUpBetweenHolesConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Ready Up", "Enabled", true, "Require every active Pro Golf player to press A before the host advances from the end-of-hole scoreboard."); grantCheckIntervalConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GrantCheckIntervalSeconds", 0.5f, "How often the host checks whether every Pro Golf player needs a cart."); longestDriveMinimumMetersConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Longest Drive", "MinimumDistanceMeters", 15f, "Minimum drive distance required before a Longest Drive popup can appear."); inventorySlotsField = AccessTools.Field(typeof(PlayerInventory), "slots"); itemPoolSpawnChancesField = AccessTools.Field(typeof(ItemPool), "spawnChances"); itemSpawnerVisualsField = AccessTools.Field(typeof(ItemSpawner), "visuals"); itemSpawnerPickupColliderField = AccessTools.Field(typeof(ItemSpawner), "pickUpCollider"); itemSpawnerVisualsFillingObjectField = AccessTools.Field(typeof(ItemSpawnerVisuals), "fillingObj"); itemSpawnerVisualsIdleObjectField = AccessTools.Field(typeof(ItemSpawnerVisuals), "idleObj"); itemSpawnerVisualsFillRendererField = AccessTools.Field(typeof(ItemSpawnerVisuals), "fillMeshRenderer"); itemSpawnerVisualsAnimatorField = AccessTools.Field(typeof(ItemSpawnerVisuals), "animator"); checkpointVisualCenterField = AccessTools.Field(typeof(Checkpoint), "visualCenter"); checkpointBaseMeshField = AccessTools.Field(typeof(Checkpoint), "baseMesh"); checkpointScreenMeshField = AccessTools.Field(typeof(Checkpoint), "screenMesh"); checkpointAnimatorField = AccessTools.Field(typeof(Checkpoint), "animator"); scoreboardEntryStatsBackgroundField = AccessTools.Field(typeof(ScoreboardEntry), "statsBackground"); scoreboardEntryNameField = AccessTools.Field(typeof(ScoreboardEntry), "name"); scoreboardEntryParentField = AccessTools.Field(typeof(Scoreboard), "entryParent"); scoreboardBestHoleScoreStatField = AccessTools.Field(typeof(Scoreboard), "bestHoleScore"); scoreboardLongestChipInStatField = AccessTools.Field(typeof(Scoreboard), "longestChipIn"); scoreboardItemPickupsStatField = AccessTools.Field(typeof(Scoreboard), "itemPickups"); scoreboardKnockoutRatioStatField = AccessTools.Field(typeof(Scoreboard), "knockoutRatio"); scoreboardStatLabelField = AccessTools.Field(typeof(ScoreboardStat), "label"); golfBallIsInHoleField = AccessTools.Field(typeof(GolfBall), "isInHole"); scoreboardMarkDirtyMethod = AccessTools.Method(typeof(Scoreboard), "MarkDirty", (Type[])null, (Type[])null); playerPopUpTextMethod = AccessTools.Method(typeof(PlayerInfo), "PopUpText", new Type[2] { typeof(string), typeof(bool) }, (Type[])null); harmony = new Harmony("codex.superbattlegolf.progolfplus"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Pro Golf Plus 0.1.43 loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } DestroyTopAnnouncementStyles(); DestroyReadyUpStyles(); if (instance == this) { instance = null; } } private void OnGUI() { DrawTopAnnouncement(); } private void Update() { PollLobbyCompatibility(); PollReadyUpInput(); PollReadyUpScoreboards(); PollCartFlipStats(); if (IsProGolfScoringActive()) { TrackCurrentHolePar(); ResetLongestDriveIfHoleChanged(); } if (IsActiveProGolf() && !(Time.unscaledTime < nextGrantCheckTime)) { nextGrantCheckTime = Time.unscaledTime + Mathf.Max(0.25f, grantCheckIntervalConfig.Value); TryEnsureAllPlayersHaveProGolfLoadout(); TrySuppressAllItemSpawners(); TrySuppressCheckpoints(); } } private static bool IsActiveProGolf() { if ((Object)(object)instance == (Object)null || !instance.enabledConfig.Value) { return false; } if (NetworkServer.active && !allLobbyMembersCompatible) { return false; } if (!HostAllowsClientProGolf()) { return false; } if (IsCurrentPresetProGolf()) { return IsMatchUnderway(); } return false; } private static bool IsMatchUnderway() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 MatchState matchState = CourseManager.MatchState; if ((int)matchState >= 1) { return (int)matchState < 6; } return false; } private static bool IsProGolfScoringActive() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if ((Object)(object)instance == (Object)null || !instance.enabledConfig.Value) { return false; } if (NetworkServer.active && !allLobbyMembersCompatible) { return false; } if (!HostAllowsClientProGolf()) { return false; } if (IsCurrentPresetProGolf()) { return (int)CourseManager.MatchState >= 1; } return false; } private static bool IsCurrentPresetProGolf() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 MatchSetupRules val = FindMatchSetupRules(); if ((Object)(object)val != (Object)null) { return (int)val.CurrentPreset == 1; } return false; } private static bool IsProGolfScoreboardState() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if ((Object)(object)instance != (Object)null && instance.enabledConfig.Value && IsCurrentPresetProGolf()) { return (int)CourseManager.MatchState == 6; } return false; } private static bool HostAllowsClientProGolf() { if (NetworkClient.active && !NetworkServer.active && hasObservedActiveState) { return lastObservedActiveState; } return true; } private static void TrackCurrentHolePar() { int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (currentHoleGlobalIndex >= 0) { if (lastParTrackedHoleIndex != int.MinValue && currentHoleGlobalIndex < lastParTrackedHoleIndex) { parByHoleIndex.Clear(); } lastParTrackedHoleIndex = currentHoleGlobalIndex; int currentHoleParSafe = GetCurrentHoleParSafe(); if (currentHoleParSafe > 0) { parByHoleIndex[currentHoleGlobalIndex] = currentHoleParSafe; } } } private static void ResetLongestDriveIfHoleChanged() { int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (currentHoleGlobalIndex != longestDriveHoleIndex) { longestDriveHoleIndex = currentHoleGlobalIndex; longestDriveAnnounced = false; closestToPinAnnounced = false; holeStatsAnnounced = false; readyGateHoleIndex = int.MinValue; readyGateCountdownTriggeredHoleIndex = int.MinValue; localReadyHoleIndex = int.MinValue; observedReadyGateHoleIndex = int.MinValue; nextReadyGateLogTime = 0f; nextReadyStateBlockLogTime = 0f; activeDrives.Clear(); firstDriveResults.Clear(); closestToPinResults.Clear(); perfectShotCounts.Clear(); cartBestFlipStreaks.Clear(); scoreboardRowRelativeScoreTexts.Clear(); holeStatsLongestDriveDistances.Clear(); holeStatsClosestToPinDistances.Clear(); holeStatsChipInDistances.Clear(); holeOutPopupsShown.Clear(); cartFlipStates.Clear(); suppressedItemSpawners.Clear(); suppressedCheckpoints.Clear(); cachedCarts.Clear(); staleCarts.Clear(); } } private static void PollLobbyCompatibility() { //IL_0051: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) if (Time.unscaledTime < nextLobbyPollTime) { return; } nextLobbyPollTime = Time.unscaledTime + 1f; Lobby lobby = default(Lobby); if (!BNetworkManager.TryGetSteamLobby(ref lobby)) { if (!NetworkServer.active && !NetworkClient.active) { allLobbyMembersCompatible = true; incompatibleLobbyMembers = string.Empty; hasObservedActiveState = false; lastObservedActiveState = false; } return; } PublishLocalMemberVersion(lobby); PollActiveState(lobby); PollProGolfAnnouncement(lobby); PollProGolfHoleStats(lobby); PollReadyGateState(lobby); if (NetworkServer.active) { UpdateLobbyCompatibility(lobby); PublishActiveState(lobby, IsActiveProGolf() || IsProGolfScoreboardState()); } } private static void PollReadyGateState(Lobby lobby) { string data = ((Lobby)(ref lobby)).GetData("codex_progolfplus_ready_gate_version"); if (!string.IsNullOrEmpty(data) && !(data == lastObservedReadyGateVersion)) { lastObservedReadyGateVersion = data; observedReadyGateHoleIndex = (int.TryParse(((Lobby)(ref lobby)).GetData("codex_progolfplus_ready_gate_hole"), out var result) ? result : int.MinValue); MarkScoreboardsDirty(); } } private static void PollProGolfHoleStats(Lobby lobby) { string data = ((Lobby)(ref lobby)).GetData("codex_progolfplus_hole_stats_version"); if (!string.IsNullOrEmpty(data) && !(data == lastObservedHoleStatsVersion)) { lastObservedHoleStatsVersion = data; ApplyHoleStatsPayload(((Lobby)(ref lobby)).GetData("codex_progolfplus_hole_stats_payload")); MarkScoreboardsDirty(); } } private static void PublishActiveState(Lobby lobby, bool active) { if (active != lastPublishedActiveState || string.IsNullOrEmpty(((Lobby)(ref lobby)).GetData("codex_progolfplus_active"))) { lastPublishedActiveState = active; ((Lobby)(ref lobby)).SetData("codex_progolfplus_active", active ? "1" : "0"); ((Lobby)(ref lobby)).SetData("codex_progolfplus_active_version", Time.unscaledTime.ToString("R")); ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Published Pro Golf Plus active lobby state: {active}."); } } } private static void PollActiveState(Lobby lobby) { string data = ((Lobby)(ref lobby)).GetData("codex_progolfplus_active_version"); if (!string.IsNullOrEmpty(data) && !(data == lastObservedActiveVersion)) { bool flag = ((Lobby)(ref lobby)).GetData("codex_progolfplus_active") == "1"; hasObservedActiveState = true; lastObservedActiveState = flag; lastObservedActiveVersion = data; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Observed Pro Golf Plus active lobby state: {flag}."); } } } private static void PollProGolfAnnouncement(Lobby lobby) { string data = ((Lobby)(ref lobby)).GetData("codex_progolfplus_announcement_version"); if (!string.IsNullOrEmpty(data) && !(data == lastObservedAnnouncementVersion)) { lastObservedAnnouncementVersion = data; string data2 = ((Lobby)(ref lobby)).GetData("codex_progolfplus_announcement_text"); if (!string.IsNullOrEmpty(data2)) { ShowTopAnnouncement(data2); } } } private static void PublishLocalMemberVersion(Lobby lobby) { if (SteamClient.IsValid && !(Time.unscaledTime < nextLocalMemberVersionPublishTime)) { nextLocalMemberVersionPublishTime = Time.unscaledTime + 2f; ((Lobby)(ref lobby)).SetMemberData("codex_progolfplus_member_version", "0.1.43"); } } private unsafe static void UpdateLobbyCompatibility(Lobby lobby) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (!string.Equals(((Lobby)(ref lobby)).GetData("codex_progolfplus_required_version"), "0.1.43", StringComparison.Ordinal)) { ((Lobby)(ref lobby)).SetData("codex_progolfplus_required_version", "0.1.43"); } List<string> list = new List<string>(); foreach (Friend member in ((Lobby)(ref lobby)).Members) { Friend current = member; string memberData = ((Lobby)(ref lobby)).GetMemberData(current, "codex_progolfplus_member_version"); if (!string.Equals(memberData, "0.1.43", StringComparison.Ordinal)) { string? text; if (!string.IsNullOrEmpty(((Friend)(ref current)).Name)) { text = ((Friend)(ref current)).Name; } else { SteamId id = current.Id; text = ((object)(*(SteamId*)(&id))/*cast due to .constrained prefix*/).ToString(); } string text2 = text; list.Add(string.IsNullOrEmpty(memberData) ? (text2 + " (missing Pro Golf Plus 0.1.43)") : (text2 + " (Pro Golf Plus " + memberData + ", needs 0.1.43)")); } } allLobbyMembersCompatible = list.Count == 0; incompatibleLobbyMembers = string.Join(", ", list); if (!allLobbyMembersCompatible && Time.unscaledTime >= nextCompatibilityWarningTime) { nextCompatibilityWarningTime = Time.unscaledTime + 10f; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogWarning((object)("Pro Golf Plus disabled until every lobby member is running Pro Golf Plus 0.1.43: " + incompatibleLobbyMembers)); } } } private static MatchSetupRules FindMatchSetupRules() { if (SingletonNetworkBehaviour<MatchSetupRules>.HasInstance) { return SingletonNetworkBehaviour<MatchSetupRules>.Instance; } if (SingletonBehaviour<MatchSetupRules>.HasInstance) { return SingletonBehaviour<MatchSetupRules>.Instance; } return Object.FindFirstObjectByType<MatchSetupRules>((FindObjectsInactive)1); } private void TryEnsureAllPlayersHaveProGolfLoadout() { if (!NetworkServer.active) { return; } int num = 0; int num2 = 0; PlayerInventory[] array = Object.FindObjectsByType<PlayerInventory>((FindObjectsSortMode)0); foreach (PlayerInventory val in array) { if (!((Object)(object)val == (Object)null)) { num++; if (EnsureProGolfLoadout(val)) { num2++; } } } if (num2 > 0) { ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Ensured Pro Golf loadout for {num2}/{num} player inventories."); } } } private static void TrySuppressAllItemSpawners() { if (!IsActiveProGolf()) { return; } ItemSpawner[] array = Object.FindObjectsByType<ItemSpawner>((FindObjectsSortMode)0); foreach (ItemSpawner val in array) { if ((Object)(object)val != (Object)null) { SuppressItemSpawner(val); } } } private static void SuppressItemSpawner(ItemSpawner spawner) { if ((Object)(object)spawner == (Object)null) { return; } if (suppressedItemSpawners.Contains(spawner)) { if (NetworkServer.active) { if (spawner.NetworkhasItemBox) { spawner.NetworkhasItemBox = false; } if (spawner.NetworkvisualsFill != 0f) { spawner.NetworkvisualsFill = 0f; } } return; } if (NetworkServer.active) { spawner.NetworkhasItemBox = false; spawner.NetworkvisualsFill = 0f; } object? obj = itemSpawnerPickupColliderField?.GetValue(spawner); Collider val = (Collider)((obj is Collider) ? obj : null); if ((Object)(object)val != (Object)null) { val.enabled = false; } object obj2 = itemSpawnerVisualsField?.GetValue(spawner); object? obj3 = itemSpawnerVisualsFillingObjectField?.GetValue(obj2); SetSpawnerVisualObjectActive((GameObject)((obj3 is GameObject) ? obj3 : null), active: false); object? obj4 = itemSpawnerVisualsIdleObjectField?.GetValue(obj2); SetSpawnerVisualObjectActive((GameObject)((obj4 is GameObject) ? obj4 : null), active: false); object? obj5 = itemSpawnerVisualsFillRendererField?.GetValue(obj2); MeshRenderer val2 = (MeshRenderer)((obj5 is MeshRenderer) ? obj5 : null); if ((Object)(object)val2 != (Object)null) { ((Renderer)val2).enabled = false; } object? obj6 = itemSpawnerVisualsAnimatorField?.GetValue(obj2); Behaviour val3 = (Behaviour)((obj6 is Behaviour) ? obj6 : null); if ((Object)(object)val3 != (Object)null) { val3.enabled = false; } Renderer[] componentsInChildren = ((Component)spawner).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } suppressedItemSpawners.Add(spawner); } private static void SetSpawnerVisualObjectActive(GameObject gameObject, bool active) { if ((Object)(object)gameObject != (Object)null && gameObject.activeSelf != active) { gameObject.SetActive(active); } } private static void ShowTopAnnouncement(string text) { SplitAnnouncementText(text, out topAnnouncementText, out topAnnouncementDetailText); topAnnouncementVisibleUntil = Time.unscaledTime + (text.StartsWith("Hole Stats:", StringComparison.Ordinal) ? 8f : 6f); } private static void DrawTopAnnouncement() { //IL_00ba: 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_014a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(topAnnouncementText) && !(Time.unscaledTime >= topAnnouncementVisibleUntil)) { EnsureTopAnnouncementStyles(); float num = Mathf.Clamp((float)Screen.width * 0.78f, 620f, 1060f); int num2 = ((!string.IsNullOrEmpty(topAnnouncementDetailText)) ? topAnnouncementDetailText.Split(new char[1] { '\n' }).Length : 0); float num3 = (string.IsNullOrEmpty(topAnnouncementDetailText) ? 104f : (100f + Mathf.Max(42f, (float)num2 * 34f))); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, Mathf.Max(64f, (float)Screen.height * 0.28f), num, num3); GUI.Box(val, GUIContent.none, topAnnouncementBoxStyle); GUI.Label(new Rect(((Rect)(ref val)).x + 26f, ((Rect)(ref val)).y + 20f, ((Rect)(ref val)).width - 52f, 64f), topAnnouncementText, topAnnouncementTextStyle); if (!string.IsNullOrEmpty(topAnnouncementDetailText)) { GUI.Label(new Rect(((Rect)(ref val)).x + 26f, ((Rect)(ref val)).y + 82f, ((Rect)(ref val)).width - 52f, ((Rect)(ref val)).height - 92f), topAnnouncementDetailText, topAnnouncementDetailStyle); } } } private static void EnsureTopAnnouncementStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0076: 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) //IL_0089: Expected O, but got Unknown //IL_008e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown if (topAnnouncementBoxStyle == null) { topAnnouncementBoxTexture = CreateStripedGuiTexture(new Color(0.05f, 0.16f, 0.27f, 0.82f), new Color(0.12f, 0.3f, 0.47f, 0.82f)); GUIStyle val = new GUIStyle(GUI.skin.box); val.normal.background = topAnnouncementBoxTexture; val.border = new RectOffset(14, 14, 14, 14); val.padding = new RectOffset(22, 22, 18, 18); topAnnouncementBoxStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 46, fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; val2.wordWrap = false; val2.clipping = (TextClipping)1; topAnnouncementTextStyle = val2; GUIStyle val3 = new GUIStyle(topAnnouncementTextStyle) { fontSize = 34, wordWrap = true }; val3.normal.textColor = new Color(0.82f, 0.86f, 0.9f, 1f); topAnnouncementDetailStyle = val3; } } private static void SplitAnnouncementText(string text, out string title, out string detail) { title = text; detail = string.Empty; int num = text.IndexOf(':'); if (num >= 0 && num < text.Length - 1) { title = text.Substring(0, num + 1).Trim(); detail = text.Substring(num + 1).Trim(); } } private static Texture2D CreateGuiTexture(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); ((Object)val).hideFlags = (HideFlags)61; return val; } private static Texture2D CreateStripedGuiTexture(Color baseColor, Color stripeColor) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { bool flag = (j + i) / 8 % 2 == 0; val.SetPixel(j, i, flag ? stripeColor : baseColor); } } ((Texture)val).wrapMode = (TextureWrapMode)0; val.Apply(); ((Object)val).hideFlags = (HideFlags)61; return val; } private static void DestroyTopAnnouncementStyles() { if ((Object)(object)topAnnouncementBoxTexture != (Object)null) { Object.Destroy((Object)(object)topAnnouncementBoxTexture); topAnnouncementBoxTexture = null; } topAnnouncementBoxStyle = null; topAnnouncementTextStyle = null; topAnnouncementDetailStyle = null; } private static void PollReadyUpInput() { if (NetworkServer.active && IsReadyScoreboardWindowActive()) { OpenReadyGateForCurrentHole(); } if (!IsReadyUpWindowActive()) { return; } if (WasReadyPressedThisFrame()) { PublishLocalReadyForCurrentHole(); } if (NetworkServer.active && readyGateHoleIndex == CourseManager.CurrentHoleGlobalIndex && readyGateCountdownTriggeredHoleIndex != readyGateHoleIndex && AreAllActivePlayersReadyForCurrentHole()) { readyGateCountdownTriggeredHoleIndex = readyGateHoleIndex; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)"All Pro Golf players are ready; starting next hole."); } InvokeServerStartNextMatch(); } } private static void PollReadyUpScoreboards() { if (!(Time.unscaledTime < nextReadyScoreboardRefreshTime)) { nextReadyScoreboardRefreshTime = Time.unscaledTime + 0.25f; Scoreboard[] array = Object.FindObjectsByType<Scoreboard>((FindObjectsInactive)1, (FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { UpdateScoreboardReadyUpPanel(array[i]); } if (IsReadyUpWindowActive()) { MarkScoreboardsDirty(); } } } private static bool WasReadyPressedThisFrame() { try { return (Keyboard.current != null && (((ButtonControl)Keyboard.current.aKey).wasPressedThisFrame || ((ButtonControl)Keyboard.current.bKey).wasPressedThisFrame || ((ButtonControl)Keyboard.current.xKey).wasPressedThisFrame)) || (Gamepad.current != null && (Gamepad.current.buttonEast.wasPressedThisFrame || Gamepad.current.buttonWest.wasPressedThisFrame || Gamepad.current.buttonSouth.wasPressedThisFrame)); } catch { return false; } } private static bool IsReadyUpWindowActive() { if ((Object)(object)instance != (Object)null && instance.readyUpBetweenHolesConfig.Value && IsProGolfScoringActive() && Scoreboard.IsVisible && (IsReadyScoreboardWindowActive() || IsReadyGateOpenForCurrentHole())) { return GetActivePlayerGuids().Count > 0; } return false; } private static bool IsReadyScoreboardWindowActive() { if ((Object)(object)instance != (Object)null && instance.readyUpBetweenHolesConfig.Value && IsProGolfScoringActive() && Scoreboard.IsVisible && AllActivePlayersResolvedForCurrentHole()) { return GetActivePlayerGuids().Count > 0; } return false; } private static bool IsReadyGateOpenForCurrentHole() { int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (readyGateHoleIndex != currentHoleGlobalIndex) { return observedReadyGateHoleIndex == currentHoleGlobalIndex; } return true; } private static void OpenReadyGateForCurrentHole() { int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (readyGateHoleIndex != currentHoleGlobalIndex) { readyGateHoleIndex = currentHoleGlobalIndex; readyGateCountdownTriggeredHoleIndex = int.MinValue; PublishReadyGateState(currentHoleGlobalIndex); MarkScoreboardsDirty(); ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Opened Pro Golf ready-up gate for hole {currentHoleGlobalIndex}."); } } } private static void PublishReadyGateState(int holeIndex) { Lobby val = default(Lobby); if (NetworkServer.active && BNetworkManager.TryGetSteamLobby(ref val)) { observedReadyGateHoleIndex = holeIndex; ((Lobby)(ref val)).SetData("codex_progolfplus_ready_gate_hole", holeIndex.ToString()); ((Lobby)(ref val)).SetData("codex_progolfplus_ready_gate_version", $"{holeIndex}:{Time.unscaledTime:R}"); } } private static void PublishLocalReadyForCurrentHole() { int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (localReadyHoleIndex != currentHoleGlobalIndex) { localReadyHoleIndex = currentHoleGlobalIndex; Lobby val = default(Lobby); if (BNetworkManager.TryGetSteamLobby(ref val)) { ((Lobby)(ref val)).SetMemberData("codex_progolfplus_ready_hole", currentHoleGlobalIndex.ToString()); } MarkScoreboardsDirty(); ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Published local Pro Golf ready-up for hole {currentHoleGlobalIndex}."); } } } private static bool AreAllActivePlayersReadyForCurrentHole() { if (!IsReadyGateOpenForCurrentHole()) { return false; } List<ulong> activePlayerGuids = GetActivePlayerGuids(); if (activePlayerGuids.Count == 0) { return false; } foreach (ulong item in activePlayerGuids) { if (!IsPlayerReadyForCurrentHole(item)) { return false; } } return true; } private static bool IsPlayerReadyForCurrentHole(ulong playerGuid) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; if (playerGuid != 0L && playerGuid == GetLocalPlayerGuid() && localReadyHoleIndex == currentHoleGlobalIndex) { return true; } Lobby val = default(Lobby); if (!BNetworkManager.TryGetSteamLobby(ref val)) { return false; } foreach (Friend member in ((Lobby)(ref val)).Members) { if (TryGetFriendSteamId(member, out var steamId) && steamId == playerGuid) { return string.Equals(((Lobby)(ref val)).GetMemberData(member, "codex_progolfplus_ready_hole"), currentHoleGlobalIndex.ToString(), StringComparison.Ordinal); } } return false; } private static ulong GetLocalPlayerGuid() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return CourseManager.GetLocalPlayerState().playerGuid; } private unsafe static bool TryGetFriendSteamId(Friend member, out ulong steamId) { return ulong.TryParse(((object)(*(SteamId*)(&member.Id))/*cast due to .constrained prefix*/).ToString(), out steamId); } private static bool TryHoldForReadyUp(CourseManager courseManager) { if ((Object)(object)instance == (Object)null || !instance.readyUpBetweenHolesConfig.Value || !NetworkServer.active || (Object)(object)courseManager == (Object)null) { return false; } int currentHoleGlobalIndex = CourseManager.CurrentHoleGlobalIndex; OpenReadyGateForCurrentHole(); if (AreAllActivePlayersReadyForCurrentHole()) { return false; } if (Time.unscaledTime >= nextReadyGateLogTime) { nextReadyGateLogTime = Time.unscaledTime + 4f; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Holding Pro Golf end-of-hole countdown for ready-up on hole {currentHoleGlobalIndex}: {BuildReadyStatusSummary()}."); } } return true; } private static bool ShouldBlockNativeEndCountdown(CourseManager courseManager) { if ((Object)(object)instance == (Object)null || !instance.readyUpBetweenHolesConfig.Value || !NetworkServer.active || (Object)(object)courseManager == (Object)null || !IsProGolfScoringActive()) { return false; } if (!AllActivePlayersResolved(courseManager)) { if (Time.unscaledTime >= nextReadyGateLogTime) { nextReadyGateLogTime = Time.unscaledTime + 4f; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)"Holding Pro Golf end-of-hole countdown because active players are still playing."); } } MatchEndCountdown.Hide(); return true; } return false; } private static void MaintainReadyUpHold() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 if ((Object)(object)instance == (Object)null || !instance.readyUpBetweenHolesConfig.Value || !IsProGolfScoringActive()) { return; } if (ShouldSuppressReadyCountdownUi()) { MatchEndCountdown.Hide(); } if (NetworkServer.active && SingletonNetworkBehaviour<CourseManager>.HasInstance) { CourseManager val = SingletonNetworkBehaviour<CourseManager>.Instance; if (!((Object)(object)val == (Object)null) && ShouldBlockNativeEndCountdown(val) && ((int)CourseManager.MatchState == 4 || (int)CourseManager.MatchState == 5)) { RollBackReadyUpMatchState(val, (MatchState)3); } } } private static bool ShouldSuppressReadyCountdownUi() { if ((Object)(object)instance == (Object)null || !instance.readyUpBetweenHolesConfig.Value || !IsProGolfScoringActive()) { return false; } if (Scoreboard.IsVisible && IsReadyGateOpenForCurrentHole()) { return !AreAllActivePlayersReadyForCurrentHole(); } return false; } private static void RollBackReadyUpMatchState(CourseManager courseManager, MatchState fallbackState) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)courseManager == (Object)null || suppressReadyMatchStateRollback) { return; } suppressReadyMatchStateRollback = true; try { courseManager.NetworkmatchState = fallbackState; MatchEndCountdown.Hide(); } finally { suppressReadyMatchStateRollback = false; } } private static bool TryBlockReadyUpMatchStateChange(CourseManager courseManager, MatchState requestedState, ref MatchState replacementState) { return false; } private static bool IsReadyHoldState(MatchState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((int)state != 4 && (int)state != 5) { return (int)state == 6; } return true; } private static bool ShouldBlockNextMatchForReadyUp(CourseManager courseManager) { if ((Object)(object)instance == (Object)null || !instance.readyUpBetweenHolesConfig.Value || !NetworkServer.active || (Object)(object)courseManager == (Object)null || !IsProGolfScoringActive()) { return false; } if (!Scoreboard.IsVisible && !IsReadyGateOpenForCurrentHole()) { return false; } OpenReadyGateForCurrentHole(); if (AreAllActivePlayersReadyForCurrentHole()) { return false; } MatchEndCountdown.Hide(); if (Time.unscaledTime >= nextReadyStateBlockLogTime) { nextReadyStateBlockLogTime = Time.unscaledTime + 2f; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)("Blocked Pro Golf next-hole start until scoreboard ready-up completes: " + BuildReadyStatusSummary() + ".")); } } return true; } private static IEnumerator EmptyReadyUpHoldRoutine() { yield break; } private static void InvokeBeginCountdownToMatchEnd() { if (SingletonNetworkBehaviour<CourseManager>.HasInstance) { AccessTools.Method(typeof(CourseManager), "BeginCountdownToMatchEnd", (Type[])null, (Type[])null)?.Invoke(SingletonNetworkBehaviour<CourseManager>.Instance, Array.Empty<object>()); } } private static void InvokeServerStartNextMatch() { if (!NetworkServer.active || !SingletonNetworkBehaviour<CourseManager>.HasInstance) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(CourseManager), "ServerStartNextMatch", (Type[])null, (Type[])null); if (methodInfo == null) { ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogWarning((object)"Could not find CourseManager.ServerStartNextMatch for Pro Golf ready-up."); } } else { methodInfo.Invoke(SingletonNetworkBehaviour<CourseManager>.Instance, new object[1] { false }); } } private static string BuildReadyStatusSummary() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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) List<string> list = new List<string>(); foreach (PlayerState sortedActivePlayerState in GetSortedActivePlayerStates()) { list.Add(GetPlayerName(null, sortedActivePlayerState.playerGuid) + "=" + (IsPlayerReadyForCurrentHole(sortedActivePlayerState.playerGuid) ? "ready" : "waiting")); } if (list.Count != 0) { return string.Join(", ", list); } return "no active players"; } private static void DrawReadyUpOverlay() { //IL_0078: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) if (!IsReadyUpWindowActive()) { return; } EnsureReadyUpStyles(); List<PlayerState> sortedActivePlayerStates = GetSortedActivePlayerStates(); float num = Mathf.Clamp((float)Screen.width * 0.3f, 360f, 520f); float num2 = 28f; float num3 = 118f + (float)Mathf.Max(1, sortedActivePlayerStates.Count) * num2; Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width - num - 32f, Mathf.Max(86f, (float)Screen.height * 0.18f), num, num3); GUI.Box(val, GUIContent.none, readyUpBoxStyle); GUI.Label(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 14f, ((Rect)(ref val)).width - 36f, 30f), "Ready for next hole", readyUpHeaderStyle); GUI.Label(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 46f, ((Rect)(ref val)).width - 36f, 28f), (localReadyHoleIndex == CourseManager.CurrentHoleGlobalIndex) ? "You are ready" : "Press X to ready up", readyUpPromptStyle); float num4 = ((Rect)(ref val)).y + 82f; foreach (PlayerState item in sortedActivePlayerStates) { string text = (IsPlayerReadyForCurrentHole(item.playerGuid) ? "[Ready]" : "[Waiting]"); GUI.Label(new Rect(((Rect)(ref val)).x + 22f, num4, ((Rect)(ref val)).width - 44f, num2), text + " " + GetPlayerName(null, item.playerGuid), readyUpRowStyle); num4 += num2; } } private static void EnsureReadyUpStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0076: 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) //IL_0089: Expected O, but got Unknown //IL_008e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0114: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown if (readyUpBoxStyle == null) { readyUpBoxTexture = CreateStripedGuiTexture(new Color(0.04f, 0.18f, 0.12f, 0.88f), new Color(0.08f, 0.3f, 0.19f, 0.88f)); GUIStyle val = new GUIStyle(GUI.skin.box); val.normal.background = readyUpBoxTexture; val.border = new RectOffset(14, 14, 14, 14); val.padding = new RectOffset(16, 16, 14, 14); readyUpBoxStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 24, fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; readyUpHeaderStyle = val2; GUIStyle val3 = new GUIStyle(readyUpHeaderStyle) { fontSize = 18, fontStyle = (FontStyle)1 }; val3.normal.textColor = new Color(0.78f, 1f, 0.72f, 1f); readyUpPromptStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, fontSize = 17, fontStyle = (FontStyle)1 }; val4.normal.textColor = Color.white; val4.clipping = (TextClipping)1; readyUpRowStyle = val4; } } private static void DestroyReadyUpStyles() { if ((Object)(object)readyUpBoxTexture != (Object)null) { Object.Destroy((Object)(object)readyUpBoxTexture); readyUpBoxTexture = null; } readyUpBoxStyle = null; readyUpHeaderStyle = null; readyUpRowStyle = null; readyUpPromptStyle = null; if ((Object)(object)proGolfReadyFlagTexture != (Object)null) { Object.Destroy((Object)(object)proGolfReadyFlagTexture); proGolfReadyFlagTexture = null; proGolfReadyFlagSprite = null; } } private static void TrySuppressCheckpoints() { if (IsActiveProGolf()) { Checkpoint[] array = Object.FindObjectsByType<Checkpoint>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { SuppressCheckpointVisuals(array[i]); } } } private static void SuppressCheckpointVisuals(Checkpoint checkpoint) { if ((Object)(object)checkpoint == (Object)null || suppressedCheckpoints.Contains(checkpoint)) { return; } object? obj = checkpointBaseMeshField?.GetValue(checkpoint); MeshRenderer val = (MeshRenderer)((obj is MeshRenderer) ? obj : null); if ((Object)(object)val != (Object)null) { ((Renderer)val).enabled = false; } object? obj2 = checkpointScreenMeshField?.GetValue(checkpoint); MeshRenderer val2 = (MeshRenderer)((obj2 is MeshRenderer) ? obj2 : null); if ((Object)(object)val2 != (Object)null) { ((Renderer)val2).enabled = false; } object? obj3 = checkpointAnimatorField?.GetValue(checkpoint); Behaviour val3 = (Behaviour)((obj3 is Behaviour) ? obj3 : null); if ((Object)(object)val3 != (Object)null) { val3.enabled = false; } object? obj4 = checkpointVisualCenterField?.GetValue(checkpoint); Transform val4 = (Transform)((obj4 is Transform) ? obj4 : null); if ((Object)(object)val4 != (Object)null) { Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Collider[] componentsInChildren2 = ((Component)val4).GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } suppressedCheckpoints.Add(checkpoint); } else { Renderer[] componentsInChildren = ((Component)checkpoint).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } suppressedCheckpoints.Add(checkpoint); } } private static SyncList<InventorySlot> GetSlots(PlayerInventory inventory) { return inventorySlotsField?.GetValue(inventory) as SyncList<InventorySlot>; } private static void EnsureSlotCount(PlayerInventory inventory) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) SyncList<InventorySlot> slots = GetSlots(inventory); if (slots != null) { while (slots.Count < 3) { slots.Add(InventorySlot.Empty); } while (slots.Count > 3) { slots.RemoveAt(slots.Count - 1); } } } private static bool IsCart(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((int)slot.itemType == 6) { return slot.remainingUses > 0; } return false; } private static bool IsCoffee(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((int)slot.itemType == 1) { return slot.remainingUses > 0; } return false; } private static bool IsSpringBoots(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((int)slot.itemType == 5) { return slot.remainingUses > 0; } return false; } private static bool IsPistol(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((int)slot.itemType == 2) { return slot.remainingUses > 0; } return false; } private static bool IsEmpty(InventorySlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if ((int)slot.itemType != 0) { return slot.remainingUses <= 0; } return true; } private static bool IsReservedPermanentSlot(PlayerInventory inventory, int index) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) if (!IsActiveProGolf() || !TryGetSlot(inventory, index, out var slot)) { return false; } if ((index != 0 || !IsCart(slot)) && (index != 1 || !IsCoffee(slot))) { if (index == 2) { return IsSpringBoots(slot); } return false; } return true; } private static bool TryGetSlot(PlayerInventory inventory, int index, out InventorySlot slot) { //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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) slot = InventorySlot.Empty; SyncList<InventorySlot> slots = GetSlots(inventory); if (slots == null || index < 0 || index >= slots.Count) { return false; } slot = slots[index]; return true; } private static bool EnsureProGolfLoadout(PlayerInventory inventory) { if (!IsActiveProGolf() || !NetworkServer.active) { return false; } SyncList<InventorySlot> slots = GetSlots(inventory); if (slots == null) { return false; } EnsureSlotCount(inventory); return (byte)(0u | (SetSlotIfDifferent(slots, 0, (ItemType)6) ? 1u : 0u) | (SetSlotIfDifferent(slots, 1, (ItemType)1) ? 1u : 0u) | (SetSlotIfDifferent(slots, 2, (ItemType)5) ? 1u : 0u) | (ClearNonPermanentItems(slots) ? 1u : 0u)) != 0; } private static bool SetSlotIfDifferent(SyncList<InventorySlot> slots, int index, ItemType itemType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) InventorySlot val = slots[index]; if (val.itemType == itemType && val.remainingUses > 0) { return false; } slots[index] = new InventorySlot(itemType, 1); return true; } private static bool ClearNonPermanentItems(SyncList<InventorySlot> slots) { //IL_0010: 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) bool result = false; for (int i = 0; i < slots.Count; i++) { if (!IsPermanentLoadoutSlot(i) && !IsEmpty(slots[i])) { slots[i] = InventorySlot.Empty; result = true; } } return result; } private static bool IsPermanentLoadoutSlot(int index) { if (index != 0 && index != 1) { return index == 2; } return true; } private static bool IsBlockedProGolfPickupItem(ItemType itemType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if ((int)itemType != 6 && (int)itemType != 1 && (int)itemType != 5 && (int)itemType != 2) { return (int)itemType == 0; } return true; } private static void MarkBallRespawnForHazardElimination(PlayerGolfer golfer, EliminationReason immediateEliminationReason) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (IsActiveProGolf() && !((Object)(object)golfer == (Object)null) && IsHazardElimination(immediateEliminationReason)) { PlayerInfo playerInfo = golfer.PlayerInfo; PlayerMovement val = ((playerInfo != null) ? playerInfo.Movement : null); GolfBall ownBall = golfer.OwnBall; if (!((Object)(object)val == (Object)null) && !((Object)(object)ownBall == (Object)null)) { forceNextRespawnAtBall.Add(val); } } } private static bool IsHazardElimination(EliminationReason reason) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)reason != 5 && (int)reason != 6) { return (int)reason == 23; } return true; } private static void RedirectHazardRespawnToBall(PlayerMovement movement, ref RespawnTarget respawnTarget) { if (IsActiveProGolf() && !((Object)(object)movement == (Object)null) && (int)respawnTarget == 0 && forceNextRespawnAtBall.Remove(movement)) { respawnTarget = (RespawnTarget)1; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)"Redirected Pro Golf Plus hazard respawn to player's ball."); } } } private static bool TryRespawnHazardEliminationAtBall(PlayerGolfer golfer, EliminationReason immediateEliminationReason) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!IsActiveProGolf() || !IsHazardElimination(immediateEliminationReason)) { return false; } object obj; if (golfer == null) { obj = null; } else { PlayerInfo playerInfo = golfer.PlayerInfo; obj = ((playerInfo != null) ? playerInfo.Movement : null); } PlayerMovement val = (PlayerMovement)obj; if ((Object)(object)val == (Object)null) { return false; } if (!val.TryBeginRespawn(false, (RespawnTarget)1)) { return false; } ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)"Converted Pro Golf Plus hazard elimination into a ball respawn without knockout/elimination reporting."); } return true; } private static bool IsProGolfScorePopupType(PlayerTextPopupType popupType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 if ((int)popupType != 1 && (int)popupType != 2 && (int)popupType != 3 && (int)popupType != 4 && (int)popupType != 5 && (int)popupType != 6 && (int)popupType != 7 && (int)popupType != 8 && (int)popupType != 9 && (int)popupType != 10 && (int)popupType != 11 && (int)popupType != 12 && (int)popupType != 13 && (int)popupType != 14 && (int)popupType != 15 && (int)popupType != 16 && (int)popupType != 17 && (int)popupType != 18) { return (int)popupType == 21; } return true; } private static bool HasPlayerScoredThisHole(PlayerGolfer golfer) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 PlayerState val = default(PlayerState); if ((Object)(object)golfer != (Object)null && CourseManager.TryGetPlayerState(golfer.PlayerInfo, ref val)) { return (int)val.matchResolution == 1; } return false; } private static bool AllActivePlayersResolved(CourseManager courseManager) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) SyncList<PlayerState> playerStates = CourseManager.PlayerStates; if (playerStates == null) { return false; } int num = 0; int num2 = 0; Enumerator<PlayerState> enumerator = playerStates.GetEnumerator(); try { while (enumerator.MoveNext()) { PlayerState current = enumerator.Current; if (current.isConnected && !current.isSpectator && (int)current.matchResolution != -1) { num++; if ((int)current.matchResolution != 0) { num2++; } } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } if (num > 0) { return num == num2; } return false; } private static bool TryCompareProGolfPlayerStates(PlayerState self, PlayerState other, ref int result) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (!IsProGolfScoringActive()) { return false; } if (self.courseStrokes != other.courseStrokes) { result = self.courseStrokes.CompareTo(other.courseStrokes); return true; } if (self.courseScore != other.courseScore) { result = other.courseScore.CompareTo(self.courseScore); return true; } if (self.wins != other.wins) { result = other.wins.CompareTo(self.wins); return true; } if (self.finishes != other.finishes) { result = other.finishes.CompareTo(self.finishes); return true; } if (self.courseKnockouts != other.courseKnockouts) { result = other.courseKnockouts.CompareTo(self.courseKnockouts); return true; } if (self.losses != other.losses) { result = self.losses.CompareTo(other.losses); return true; } if (!self.scoreTimestamp.Equals(other.scoreTimestamp)) { result = self.scoreTimestamp.CompareTo(other.scoreTimestamp); return true; } result = self.joinIndex.CompareTo(other.joinIndex); return true; } private static bool TryGetWeightedRandomAllowedPickupItem(ItemPool pool, out ItemType item) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected I4, but got Unknown item = (ItemType)0; if (!(itemPoolSpawnChancesField?.GetValue(pool) is Array { Length: not 0 } array)) { return false; } float num = 0f; foreach (object item2 in array) { ItemType itemType = (ItemType)AccessTools.Field(item2.GetType(), "item").GetValue(item2); float num2 = (float)AccessTools.Field(item2.GetType(), "spawnChanceWeight").GetValue(item2); if (!IsBlockedProGolfPickupItem(itemType) && num2 > 0f) { num += num2; } } if (num <= 0f) { item = (ItemType)3; return true; } float num3 = Random.value * num; foreach (object item3 in array) { ItemType val = (ItemType)AccessTools.Field(item3.GetType(), "item").GetValue(item3); float num4 = (float)AccessTools.Field(item3.GetType(), "spawnChanceWeight").GetValue(item3); if (!IsBlockedProGolfPickupItem(val) && !(num4 <= 0f)) { num3 -= num4; if (num3 <= 0f) { item = (ItemType)(int)val; return true; } } } item = (ItemType)3; return true; } private static void BeginDriveTracking(GolfBall ball) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active && IsActiveProGolf() && !((Object)(object)ball == (Object)null) && !((Object)(object)ball.Owner == (Object)null) && !((Object)(object)ball.Owner.PlayerInfo == (Object)null) && !((Object)(object)ball.Owner.PlayerInfo.PlayerId == (Object)null)) { ResetLongestDriveIfHoleChanged(); ulong guid = ball.Owner.PlayerInfo.PlayerId.Guid; if (!firstDriveResults.ContainsKey(guid) && !HasActiveDriveForPlayer(guid)) { activeDrives[ball] = new DriveCandidate { Player = ball.Owner.PlayerInfo, PlayerGuid = guid, StartPosition = ((Component)ball).transform.position }; } } } private static void TryCompleteDriveTracking(GolfBall ball) { //IL_0076: 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_0081: 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) if (NetworkServer.active && IsActiveProGolf() && !((Object)(object)ball == (Object)null) && ball.IsStationary && activeDrives.TryGetValue(ball, out var value)) { activeDrives.Remove(ball); if (!((Object)(object)value.Player == (Object)null) && !((Object)(object)value.Player.PlayerId == (Object)null) && !firstDriveResults.ContainsKey(value.PlayerGuid)) { Vector3 val = ((Component)ball).transform.position - value.StartPosition; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; float num = Mathf.Max(0f, instance?.longestDriveMinimumMetersConfig.Value ?? 0f); firstDriveResults[value.PlayerGuid] = new FirstDriveResult { PlayerName = GetPlayerName(value.Player, value.PlayerGuid), Distance = magnitude, IsValid = (magnitude >= num) }; TryAnnounceLongestDriveIfReady(); } } } private static void TryCaptureClosestToPinFromStationaryBall(GolfBall ball) { if (!NetworkServer.active || !IsActiveProGolf() || (Object)(object)ball == (Object)null || !ball.IsStationary || (Object)(object)ball.Owner == (Object)null || (Object)(object)ball.Owner.PlayerInfo == (Object)null || (Object)(object)ball.Owner.PlayerInfo.PlayerId == (Object)null) { return; } ResetLongestDriveIfHoleChanged(); PlayerInfo playerInfo = ball.Owner.PlayerInfo; ulong guid = playerInfo.PlayerId.Guid; if (!closestToPinResults.ContainsKey(guid) && !IsBallInHole(ball) && !HasPlayerScoredThisHole(playerInfo.AsGolfer) && TryGetDistanceToPinWithinRadius(ball, out var distanceToPin)) { closestToPinResults[guid] = new ClosestToPinResult { PlayerName = GetPlayerName(playerInfo, guid), Distance = distanceToPin, IsValid = true }; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)("Captured Closest to Pin inside 10yd radius: " + GetPlayerName(playerInfo, guid) + " " + FormatDistanceFeet(distanceToPin) + ".")); } TryAnnounceClosestToPinIfReady(); } } private static void CaptureClosestToPinOnScore(PlayerGolfer player) { if (NetworkServer.active && IsActiveProGolf()) { object obj; if (player == null) { obj = null; } else { PlayerInfo playerInfo = player.PlayerInfo; obj = ((playerInfo != null) ? playerInfo.PlayerId : null); } if (!((Object)obj == (Object)null)) { ResetLongestDriveIfHoleChanged(); _ = player.PlayerInfo.PlayerId.Guid; CaptureChipInOnScore(player); } } } private static void CaptureChipInOnScore(PlayerGolfer player) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !IsActiveProGolf()) { return; } object obj; if (player == null) { obj = null; } else { PlayerInfo playerInfo = player.PlayerInfo; obj = ((playerInfo != null) ? playerInfo.PlayerId : null); } if ((Object)obj == (Object)null) { return; } GolfHole val = FindMainHole(); GolfBall ownBall = player.OwnBall; if ((Object)(object)val == (Object)null || (Object)(object)ownBall == (Object)null) { return; } Vector3 serverLastStrokePosition = ownBall.ServerLastStrokePosition; Vector3 val2 = serverLastStrokePosition - ((Component)val).transform.position; val2.y = 0f; float magnitude = ((Vector3)(ref val2)).magnitude; if (!(magnitude < 1f) && !val.IsPointInGreenTrigger(serverLastStrokePosition)) { ulong guid = player.PlayerInfo.PlayerId.Guid; holeStatsChipInDistances[guid] = magnitude; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)("Tracked Pro Golf chip-in: " + GetPlayerName(player.PlayerInfo, guid) + " " + FormatDistanceYards(magnitude) + ".")); } } } private static void FinalizeMissingClosestToPinResults(List<ulong> activePlayers) { if (!AllActivePlayersResolvedForCurrentHole()) { return; } foreach (ulong activePlayer in activePlayers) { if (!closestToPinResults.ContainsKey(activePlayer)) { closestToPinResults[activePlayer] = new ClosestToPinResult { PlayerName = CourseManager.GetPlayerName(activePlayer), Distance = float.PositiveInfinity, IsValid = false }; } } } private static void TrackPerfectShot(PlayerGolfer player) { if (!NetworkServer.active || !IsActiveProGolf()) { return; } object obj; if (player == null) { obj = null; } else { PlayerInfo playerInfo = player.PlayerInfo; obj = ((playerInfo != null) ? playerInfo.PlayerId : null); } if ((Object)obj == (Object)null) { return; } ResetLongestDriveIfHoleChanged(); float swingNormalizedCharge = player.SwingNormalizedCharge; if (!(swingNormalizedCharge <= 0.99f) && !(swingNormalizedCharge > 1f)) { ulong guid = player.PlayerInfo.PlayerId.Guid; perfectShotCounts.TryGetValue(guid, out var value); perfectShotCounts[guid] = value + 1; ProGolfPlugin proGolfPlugin = instance; if (proGolfPlugin != null) { ((BaseUnityPlugin)proGolfPlugin).Logger.LogInfo((object)$"Tracked Pro Golf perfect shot: {GetPlayerName(player.PlayerInfo, guid)} ({value + 1})."); } } } private static void PollCartFlipStats() { if (!NetworkServer.active || !IsActiveProGolf()) { cartFlipStates.Clear(); } else { if (Time.unscaledTime < nextCartFlipPollTime) { return; } nextCartFlipPollTime = Time.unscaledTime + 0.25f; ResetLongestDriveIfHoleChanged(); RefreshCachedCartsIfNeeded(); foreach (GolfCartMovement cachedCart in cachedCarts) { if (!((Object)(object)cachedCart == (Object)null)) { if (!cartFlipStates.TryGetValue(cachedCart, out var value)) { value = new CartFlipState { Wheels = ((Component)cachedCart).GetComponentsInChildren<WheelCollider>(true) }; cartFlipStates[cachedCart] = value; } UpdateCartFlipState(cachedCart, value); } } staleCarts.Clear(); foreach (GolfCartMovement key in cartFlipStates.Keys) { if ((Object)(object)key == (Object)null || !cachedCarts.Contains(key)) { staleCarts.Add(key); } } foreach (GolfCartMovement staleCart in staleCarts) { cartFlipStates.Remove(staleCart); } } } private static void RefreshCachedCartsIfNeeded() { if (Time.unscaledTime < nextCartDiscoveryPollTime) { return; } nextCartDiscoveryPollTime = Time.unscaledTime + 1f; cachedCarts.Clear(); GolfCartMovement[] array = Object.FindObjectsByType<GolfCartMovement>((FindObjectsSortMode)0); foreach (GolfCartMoveme