using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[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("ForeverGolfCart")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ForeverGolfCart")]
[assembly: AssemblyTitle("ForeverGolfCart")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ForeverGolfCart
{
internal static class InputBridge
{
internal static bool WasPressedThisFrame(KeyCode keyCode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected I4, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
switch (keyCode - 323)
{
case 0:
if (Mouse.current != null)
{
return Mouse.current.leftButton.wasPressedThisFrame;
}
return false;
case 1:
if (Mouse.current != null)
{
return Mouse.current.rightButton.wasPressedThisFrame;
}
return false;
case 2:
if (Mouse.current != null)
{
return Mouse.current.middleButton.wasPressedThisFrame;
}
return false;
case 3:
if (Mouse.current != null)
{
return Mouse.current.backButton.wasPressedThisFrame;
}
return false;
case 4:
if (Mouse.current != null)
{
return Mouse.current.forwardButton.wasPressedThisFrame;
}
return false;
default:
{
Key val = TranslateKey(keyCode);
if ((int)val == 0 || Keyboard.current == null)
{
return false;
}
return ((ButtonControl)Keyboard.current[val]).wasPressedThisFrame;
}
}
}
internal static bool IsHeld(KeyCode keyCode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected I4, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
switch (keyCode - 323)
{
case 0:
if (Mouse.current != null)
{
return Mouse.current.leftButton.isPressed;
}
return false;
case 1:
if (Mouse.current != null)
{
return Mouse.current.rightButton.isPressed;
}
return false;
case 2:
if (Mouse.current != null)
{
return Mouse.current.middleButton.isPressed;
}
return false;
case 3:
if (Mouse.current != null)
{
return Mouse.current.backButton.isPressed;
}
return false;
case 4:
if (Mouse.current != null)
{
return Mouse.current.forwardButton.isPressed;
}
return false;
default:
{
Key val = TranslateKey(keyCode);
if ((int)val == 0 || Keyboard.current == null)
{
return false;
}
return ((ButtonControl)Keyboard.current[val]).isPressed;
}
}
}
private static Key TranslateKey(KeyCode keyCode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Invalid comparison between Unknown and I4
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Expected I4, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Expected I4, but got Unknown
//IL_0040: 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_0071: Expected I4, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Invalid comparison between Unknown and I4
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
if ((int)keyCode <= 27)
{
if ((int)keyCode <= 9)
{
if ((int)keyCode == 8)
{
return (Key)65;
}
if ((int)keyCode == 9)
{
return (Key)3;
}
}
else
{
if ((int)keyCode == 13)
{
return (Key)2;
}
if ((int)keyCode == 27)
{
return (Key)60;
}
}
}
else if ((int)keyCode <= 57)
{
if ((int)keyCode == 32)
{
return (Key)1;
}
switch (keyCode - 48)
{
case 0:
return (Key)50;
case 1:
return (Key)41;
case 2:
return (Key)42;
case 3:
return (Key)43;
case 4:
return (Key)44;
case 5:
return (Key)45;
case 6:
return (Key)46;
case 7:
return (Key)47;
case 8:
return (Key)48;
case 9:
return (Key)49;
}
}
else
{
switch (keyCode - 97)
{
default:
switch (keyCode - 273)
{
case 9:
return (Key)94;
case 10:
return (Key)95;
case 11:
return (Key)96;
case 12:
return (Key)97;
case 13:
return (Key)98;
case 14:
return (Key)99;
case 15:
return (Key)100;
case 16:
return (Key)101;
case 17:
return (Key)102;
case 18:
return (Key)103;
case 19:
return (Key)104;
case 20:
return (Key)105;
case 31:
return (Key)51;
case 30:
return (Key)52;
case 33:
return (Key)55;
case 32:
return (Key)56;
case 35:
return (Key)53;
case 34:
return (Key)54;
case 0:
return (Key)63;
case 1:
return (Key)64;
case 3:
return (Key)61;
case 2:
return (Key)62;
}
break;
case 0:
return (Key)15;
case 1:
return (Key)16;
case 2:
return (Key)17;
case 3:
return (Key)18;
case 4:
return (Key)19;
case 5:
return (Key)20;
case 6:
return (Key)21;
case 7:
return (Key)22;
case 8:
return (Key)23;
case 9:
return (Key)24;
case 10:
return (Key)25;
case 11:
return (Key)26;
case 12:
return (Key)27;
case 13:
return (Key)28;
case 14:
return (Key)29;
case 15:
return (Key)30;
case 16:
return (Key)31;
case 17:
return (Key)32;
case 18:
return (Key)33;
case 19:
return (Key)34;
case 20:
return (Key)35;
case 21:
return (Key)36;
case 22:
return (Key)37;
case 23:
return (Key)38;
case 24:
return (Key)39;
case 25:
return (Key)40;
case 30:
return (Key)71;
case 26:
case 27:
case 28:
case 29:
break;
}
}
return (Key)0;
}
}
[BepInPlugin("sbg.forevergolfcart", "ForeverGolfCart", "0.3.2")]
public sealed class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(GolfCartInfo), "OnStartClient")]
internal static class Patch_GolfCartInfo_OnStartClient
{
private static void Postfix(GolfCartInfo __instance)
{
if (!((Object)(object)Instance == (Object)null) && Instance.pastelTintEnabledConfig.Value && !((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).netId != 0 && ClientTintedCarts.Contains(((NetworkBehaviour)__instance).netId))
{
ApplyPastelTint(__instance);
}
}
}
public const string ModGuid = "sbg.forevergolfcart";
public const string ModName = "ForeverGolfCart";
public const string ModVersion = "0.3.2";
internal static ManualLogSource Log;
internal static Plugin Instance;
internal ConfigEntry<float> hotkeyHoldDurationConfig;
internal ConfigEntry<KeyCode> summonKeyConfig;
internal ConfigEntry<bool> pastelTintEnabledConfig;
internal ConfigEntry<bool> verboseLoggingConfig;
private static MethodInfo serverEnterMethod;
private static readonly HashSet<uint> ServerTrackedCarts = new HashSet<uint>();
private static readonly HashSet<uint> ClientTintedCarts = new HashSet<uint>();
private static bool serializerRegistered;
private static bool serverHandlerRegistered;
private static bool clientHandlerRegistered;
private float keyHeldFor;
private bool summonedThisHold;
private void Awake()
{
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
hotkeyHoldDurationConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Spawn", "HotkeyHoldDuration", 0.4f, "Seconds to hold the summon key before the cart spawns. Prevents accidental Q taps from summoning a cart.");
summonKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Spawn", "SummonKey", (KeyCode)113, "Key to summon a cart. Any UnityEngine.KeyCode value (letters, numbers, function keys, modifiers, mouse buttons via Mouse0..4).");
pastelTintEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "PastelTintEnabled", true, "Tint summoned carts with a pastel hue derived from their netId so non-natural carts are recognisable. Each cart's color is consistent across modded clients.");
verboseLoggingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "VerboseLogging", false, "Emit lines whenever the summon key fires, the summon request lands on the server, and the cart spawns / auto-seat. Off by default.");
serverEnterMethod = AccessTools.Method(typeof(GolfCartInfo), "ServerEnter", (Type[])null, (Type[])null);
RegisterSerializers();
new Harmony("sbg.forevergolfcart").PatchAll();
Log.LogInfo((object)"ForeverGolfCart v0.3.2 loaded.");
}
private void OnDestroy()
{
}
private static void EnsureHandlersRegistered()
{
if (!serverHandlerRegistered && NetworkServer.active)
{
NetworkServer.ReplaceHandler<ForeverGolfCartSummonMsg>((Action<NetworkConnectionToClient, ForeverGolfCartSummonMsg>)OnSummonRequest, true);
serverHandlerRegistered = true;
LogVerbose("registered server handler ForeverGolfCartSummonMsg.");
}
if (!clientHandlerRegistered && NetworkClient.active)
{
NetworkClient.ReplaceHandler<ForeverGolfCartTintMsg>((Action<ForeverGolfCartTintMsg>)OnTintMessage, true);
clientHandlerRegistered = true;
LogVerbose("registered client handler ForeverGolfCartTintMsg.");
}
if (serverHandlerRegistered && !NetworkServer.active)
{
serverHandlerRegistered = false;
}
if (clientHandlerRegistered && !NetworkClient.active)
{
clientHandlerRegistered = false;
}
}
private static void RegisterSerializers()
{
if (!serializerRegistered)
{
Writer<ForeverGolfCartSummonMsg>.write = delegate
{
};
Reader<ForeverGolfCartSummonMsg>.read = (NetworkReader r) => default(ForeverGolfCartSummonMsg);
Writer<ForeverGolfCartTintMsg>.write = delegate(NetworkWriter w, ForeverGolfCartTintMsg m)
{
NetworkWriterExtensions.WriteUInt(w, m.netId);
};
Reader<ForeverGolfCartTintMsg>.read = delegate(NetworkReader r)
{
ForeverGolfCartTintMsg result = default(ForeverGolfCartTintMsg);
result.netId = NetworkReaderExtensions.ReadUInt(r);
return result;
};
serializerRegistered = true;
}
}
private void Update()
{
EnsureHandlersRegistered();
UpdateHotkey();
if (NetworkServer.active)
{
UpdateServerCartTracking();
}
}
private void UpdateHotkey()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
if (InputBridge.IsHeld(summonKeyConfig.Value))
{
keyHeldFor += Time.deltaTime;
if (!summonedThisHold && keyHeldFor >= hotkeyHoldDurationConfig.Value)
{
LogVerbose($"summon key {summonKeyConfig.Value} held for {keyHeldFor:F2}s — invoking summon.");
TrySummonCart();
summonedThisHold = true;
}
}
else
{
keyHeldFor = 0f;
summonedThisHold = false;
}
}
internal static void LogVerbose(string message)
{
if ((Object)(object)Instance != (Object)null && Instance.verboseLoggingConfig.Value)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)("ForeverGolfCart: " + message));
}
}
}
private void TrySummonCart()
{
//IL_0011: 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)
PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
if ((Object)(object)localPlayerInfo == (Object)null)
{
return;
}
GolfCartSeat activeGolfCartSeat = localPlayerInfo.ActiveGolfCartSeat;
if (!((GolfCartSeat)(ref activeGolfCartSeat)).IsValid() && (!((Object)(object)localPlayerInfo.AsGolfer != (Object)null) || !localPlayerInfo.AsGolfer.IsMatchResolved))
{
if (NetworkServer.active)
{
ServerSummonForPlayer(localPlayerInfo);
}
else if (NetworkClient.active && NetworkClient.ready)
{
NetworkClient.Send<ForeverGolfCartSummonMsg>(default(ForeverGolfCartSummonMsg), 0);
}
}
}
private static void OnSummonRequest(NetworkConnectionToClient conn, ForeverGolfCartSummonMsg _)
{
if (conn != null && !((Object)(object)((NetworkConnection)conn).identity == (Object)null))
{
PlayerInfo component = ((Component)((NetworkConnection)conn).identity).GetComponent<PlayerInfo>();
if (!((Object)(object)component == (Object)null))
{
ServerSummonForPlayer(component);
}
}
}
private static void ServerSummonForPlayer(PlayerInfo target)
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkServer.active || (Object)(object)target == (Object)null)
{
return;
}
if ((Object)(object)GameManager.GolfCartSettings == (Object)null || (Object)(object)GameManager.GolfCartSettings.Prefab == (Object)null)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)"ForeverGolfCart summon ignored: GolfCartSettings.Prefab missing.");
}
return;
}
GolfCartInfo val = Object.Instantiate<GolfCartInfo>(GameManager.GolfCartSettings.Prefab, ((Component)target).transform.position, Quaternion.Euler(0f, ((Component)target).transform.eulerAngles.y, 0f));
if ((Object)(object)val == (Object)null)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)"ForeverGolfCart: cart prefab failed to instantiate.");
}
return;
}
NetworkServer.Spawn(((Component)val).gameObject, (NetworkConnectionToClient)null);
uint netId = ((NetworkBehaviour)val).netId;
ServerTrackedCarts.Add(netId);
ClientTintedCarts.Add(netId);
LogVerbose($"summoned cart netId={netId} for {((Object)target).name} — invoking ServerEnter.");
if (serverEnterMethod != null)
{
try
{
serverEnterMethod.Invoke(val, new object[1] { target });
}
catch (Exception ex)
{
ManualLogSource log3 = Log;
if (log3 != null)
{
log3.LogWarning((object)("ForeverGolfCart: ServerEnter reflection invoke failed: " + ex.Message));
}
}
}
if ((Object)(object)Instance != (Object)null && Instance.pastelTintEnabledConfig.Value)
{
ApplyPastelTint(val);
if ((Object)(object)Instance != (Object)null)
{
((MonoBehaviour)Instance).StartCoroutine(ReapplyTintNextFrames(val));
}
}
ForeverGolfCartTintMsg foreverGolfCartTintMsg = default(ForeverGolfCartTintMsg);
foreverGolfCartTintMsg.netId = netId;
NetworkServer.SendToAll<ForeverGolfCartTintMsg>(foreverGolfCartTintMsg, 0, false);
}
private static IEnumerator ReapplyTintNextFrames(GolfCartInfo cart)
{
for (int i = 0; i < 6; i++)
{
if (!((Object)(object)cart != (Object)null))
{
break;
}
yield return null;
ApplyPastelTint(cart);
}
}
private static void OnTintMessage(ForeverGolfCartTintMsg msg)
{
ClientTintedCarts.Add(msg.netId);
if ((Object)(object)Instance == (Object)null || !Instance.pastelTintEnabledConfig.Value || !NetworkClient.spawned.TryGetValue(msg.netId, out var value) || !((Object)(object)value != (Object)null))
{
return;
}
GolfCartInfo component = ((Component)value).GetComponent<GolfCartInfo>();
if ((Object)(object)component != (Object)null)
{
ApplyPastelTint(component);
if ((Object)(object)Instance != (Object)null)
{
((MonoBehaviour)Instance).StartCoroutine(ReapplyTintNextFrames(component));
}
}
}
private void UpdateServerCartTracking()
{
if (ServerTrackedCarts.Count == 0)
{
return;
}
List<uint> list = null;
foreach (uint serverTrackedCart in ServerTrackedCarts)
{
if (!NetworkServer.spawned.TryGetValue(serverTrackedCart, out var value) || (Object)(object)value == (Object)null)
{
if (list == null)
{
list = new List<uint>();
}
list.Add(serverTrackedCart);
continue;
}
GolfCartInfo component = ((Component)value).GetComponent<GolfCartInfo>();
if ((Object)(object)component == (Object)null)
{
if (list == null)
{
list = new List<uint>();
}
list.Add(serverTrackedCart);
}
else if (IsCartFullyEmpty(component))
{
if (list == null)
{
list = new List<uint>();
}
list.Add(serverTrackedCart);
NetworkServer.Destroy(((Component)component).gameObject);
}
}
if (list == null)
{
return;
}
foreach (uint item in list)
{
ServerTrackedCarts.Remove(item);
ClientTintedCarts.Remove(item);
}
}
private static bool IsCartFullyEmpty(GolfCartInfo cart)
{
if ((Object)(object)cart.NetworkdriverSeatReserver != (Object)null)
{
return false;
}
for (int i = 0; i < cart.passengers.Count; i++)
{
if ((Object)(object)cart.passengers[i] != (Object)null)
{
return false;
}
}
return true;
}
private static void ApplyPastelTint(GolfCartInfo cart)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)cart == (Object)null)
{
return;
}
Color val = Color.HSVToRGB((float)((NetworkBehaviour)cart).netId * 0.618034f % 1f, 0.55f, 0.92f);
val.a = 1f;
Renderer[] componentsInChildren = ((Component)cart).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Material[] materials = val2.materials;
if (materials == null)
{
continue;
}
bool flag = false;
foreach (Material val3 in materials)
{
if (!((Object)(object)val3 == (Object)null))
{
if (val3.HasProperty("_Color"))
{
val3.color *= val;
flag = true;
}
if (val3.HasProperty("_BaseColor"))
{
val3.SetColor("_BaseColor", val3.GetColor("_BaseColor") * val);
flag = true;
}
}
}
if (flag)
{
val2.materials = materials;
}
}
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
internal struct ForeverGolfCartSummonMsg : NetworkMessage
{
}
internal struct ForeverGolfCartTintMsg : NetworkMessage
{
public uint netId;
}
}