using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
[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("BubbleBoi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BubbleBoi")]
[assembly: AssemblyTitle("BubbleBoi")]
[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 BubbleBoi
{
[BepInPlugin("sbg.bubbleboi", "BubbleBoi", "0.1.1")]
public sealed class Plugin : BaseUnityPlugin
{
public const string ModGuid = "sbg.bubbleboi";
public const string ModName = "BubbleBoi";
public const string ModVersion = "0.1.1";
internal static ManualLogSource Log;
private void Awake()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
WaterSurfaceProxy.EnsureCreated();
new Harmony("sbg.bubbleboi").PatchAll();
Log.LogInfo((object)"BubbleBoi v0.1.1 loaded.");
}
}
internal static class WaterSurfaceProxy
{
private static BoxCollider collider;
internal static Collider Collider
{
get
{
EnsureCreated();
return (Collider)(object)collider;
}
}
internal static void EnsureCreated()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)collider != (Object)null))
{
GameObject val = new GameObject("BubbleBoiWaterSurfaceProxy")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)val);
collider = val.AddComponent<BoxCollider>();
((Collider)collider).enabled = false;
((Collider)collider).isTrigger = false;
collider.size = new Vector3(1f, 0.1f, 1f);
}
}
}
[HarmonyPatch]
internal static class WaterWalkPatches
{
private const float DecisionLogIntervalSeconds = 1f;
private static readonly FieldInfo UprightColliderField = AccessTools.Field(typeof(PlayerMovement), "uprightCollider");
private static readonly FieldInfo GroundDataField = AccessTools.Field(typeof(PlayerMovement), "<GroundData>k__BackingField");
private static readonly MethodInfo NoClipEnabledGetter = AccessTools.PropertyGetter(typeof(PlayerMovement), "NoClipEnabled");
private static readonly Dictionary<int, double> LastDecisionLogTimes = new Dictionary<int, double>();
private static readonly Dictionary<int, bool> LastInjectedGroundState = new Dictionary<int, bool>();
[HarmonyPatch(typeof(PlayerMovement), "PerformGroundCheck")]
[HarmonyPostfix]
private static void PerformGroundCheckPostfix(PlayerMovement __instance, ref bool __result)
{
//IL_006f: 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)
//IL_0079: 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_008d: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: 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_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
if (!TryGetWaterSurfacePoint(__instance, out var waterPoint, out var reason))
{
if (__result)
{
TrackInjectedGroundState(__instance, isInjected: false);
}
else
{
MaybeLogDecision(__instance, "synthetic ground skipped: " + reason);
}
TrackInjectedGroundState(__instance, isInjected: false);
return;
}
object? obj = UprightColliderField?.GetValue(__instance);
CapsuleCollider val = (CapsuleCollider)((obj is CapsuleCollider) ? obj : null);
if ((Object)(object)val == (Object)null)
{
MaybeLogDecision(__instance, "synthetic ground skipped: uprightCollider missing");
TrackInjectedGroundState(__instance, isInjected: false);
return;
}
Vector3 val2 = ((Component)val).transform.TransformPoint(val.center);
float num = val.center.y + 0.35f;
if (val2.y - waterPoint.y > num)
{
MaybeLogDecision(__instance, $"synthetic ground skipped: water surface too far below ray origin ({val2.y - waterPoint.y:F3}m > {num:F3}m)");
TrackInjectedGroundState(__instance, isInjected: false);
return;
}
__instance.NetworkgroundTerrainType = (GroundTerrainType)0;
__instance.NetworkgroundTerrainDominantGlobalLayer = (TerrainLayer)0;
GroundDataField?.SetValue(__instance, (object)new PlayerGroundData
{
point = waterPoint,
contactPoint = waterPoint,
normal = Vector3.up,
collider = WaterSurfaceProxy.Collider,
hasRigidbody = false,
rigidbody = null
});
bool flag = __result;
__result = true;
object[] obj2 = new object[4]
{
waterPoint.y,
__instance.Position.y,
flag,
null
};
PlayerInfo playerInfo = __instance.PlayerInfo;
BoundsState? obj3;
if (playerInfo == null)
{
obj3 = null;
}
else
{
LevelBoundsTracker levelBoundsTracker = playerInfo.LevelBoundsTracker;
obj3 = ((levelBoundsTracker != null) ? new BoundsState?(levelBoundsTracker.AuthoritativeBoundsState) : null);
}
obj2[3] = obj3;
MaybeLogDecision(__instance, string.Format("synthetic ground injected at waterY={0:F3}, playerY={1:F3}, replacedVanillaGround={2}, bounds={3}", obj2));
TrackInjectedGroundState(__instance, isInjected: true);
}
[HarmonyPatch(typeof(PlayerMovement), "FixedUpdate")]
[HarmonyPostfix]
private static void FixedUpdatePostfix(PlayerMovement __instance)
{
//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_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0073: 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_0086: 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_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
if (!TryGetWaterSurfacePoint(__instance, out var waterPoint, out var _))
{
return;
}
PlayerInfo playerInfo = __instance.PlayerInfo;
if ((Object)(object)((playerInfo != null) ? playerInfo.LevelBoundsTracker : null) == (Object)null)
{
return;
}
PlayerInfo playerInfo2 = __instance.PlayerInfo;
Rigidbody val = ((playerInfo2 != null) ? playerInfo2.Rigidbody : null);
if ((Object)(object)val == (Object)null || val.isKinematic)
{
return;
}
Vector3 position = val.position;
if (!(position.y >= waterPoint.y))
{
float num = waterPoint.y - position.y;
position.y = waterPoint.y;
val.position = position;
Vector3 linearVelocity = val.linearVelocity;
if (linearVelocity.y < 0f)
{
linearVelocity.y = 0f;
val.linearVelocity = linearVelocity;
}
MaybeLogDecision(__instance, $"surface correction applied: raised by {num:F3}m to waterY={waterPoint.y:F3}", force: true);
}
}
[HarmonyPatch(typeof(PlayerMovement), "OnServerBoundsStateChanged")]
[HarmonyPrefix]
private static bool OnServerBoundsStateChangedPrefix(PlayerMovement __instance, BoundsState currentState)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
if (!BoundsStateExtensions.IsInOutOfBoundsHazard(currentState))
{
return true;
}
if (!ShouldWaterWalk(__instance))
{
MaybeLogDecision(__instance, $"server hazard passthrough: currentState={currentState}, reason=water-walk conditions not met");
return true;
}
PlayerInfo playerInfo = __instance.PlayerInfo;
if (IsWaterHazard((playerInfo != null) ? playerInfo.LevelBoundsTracker : null, currentState))
{
MaybeLogDecision(__instance, $"server water elimination suppressed: currentState={currentState}");
return false;
}
MaybeLogDecision(__instance, $"server hazard passthrough: currentState={currentState}, reason=hazard is not water");
return true;
}
private static bool TryGetWaterSurfacePoint(PlayerMovement movement, out Vector3 waterPoint, out string reason)
{
//IL_0001: 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_0075: 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_0061: Unknown result type (might be due to invalid IL or missing references)
waterPoint = default(Vector3);
reason = string.Empty;
if (!ShouldWaterWalkLocally(movement))
{
reason = "local water-walk conditions not met";
return false;
}
PlayerInfo playerInfo = movement.PlayerInfo;
LevelBoundsTracker val = ((playerInfo != null) ? playerInfo.LevelBoundsTracker : null);
if ((Object)(object)val == (Object)null)
{
reason = "level bounds tracker missing";
return false;
}
if (!IsWaterHazard(val, val.AuthoritativeBoundsState) && !val.IsInOrOverOutOfBoundsHazard())
{
reason = $"not over a water hazard (bounds={val.AuthoritativeBoundsState})";
return false;
}
waterPoint = movement.Position;
waterPoint.y = val.CurrentOutOfBoundsHazardWorldHeightLocalOnly;
return true;
}
private static bool ShouldWaterWalk(PlayerMovement movement)
{
//IL_002e: 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)
if ((Object)(object)movement == (Object)null)
{
return false;
}
if ((Object)(object)movement.PlayerInfo == (Object)null || !movement.PlayerInfo.IsElectromagnetShieldActive)
{
return false;
}
GolfCartSeat activeGolfCartSeat = movement.PlayerInfo.ActiveGolfCartSeat;
if (((GolfCartSeat)(ref activeGolfCartSeat)).IsValid())
{
return false;
}
if ((bool)(NoClipEnabledGetter?.Invoke(null, null) ?? ((object)false)))
{
return false;
}
return true;
}
private static bool ShouldWaterWalkLocally(PlayerMovement movement)
{
if ((Object)(object)movement != (Object)null && ((NetworkBehaviour)movement).isLocalPlayer)
{
return ShouldWaterWalk(movement);
}
return false;
}
private static void TrackInjectedGroundState(PlayerMovement movement, bool isInjected)
{
if (!((Object)(object)movement == (Object)null))
{
int instanceID = ((Object)movement).GetInstanceID();
if (!LastInjectedGroundState.TryGetValue(instanceID, out var value) || value != isInjected)
{
LastInjectedGroundState[instanceID] = isInjected;
MaybeLogDecision(movement, isInjected ? "synthetic ground state changed: active" : "synthetic ground state changed: inactive", force: true);
}
}
}
private static void MaybeLogDecision(PlayerMovement movement, string message, bool force = false)
{
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)movement == (Object)null || Plugin.Log == null)
{
return;
}
int instanceID = ((Object)movement).GetInstanceID();
double timeAsDouble = Time.timeAsDouble;
if (force || !LastDecisionLogTimes.TryGetValue(instanceID, out var value) || !(timeAsDouble - value < 1.0))
{
LastDecisionLogTimes[instanceID] = timeAsDouble;
PlayerInfo playerInfo = movement.PlayerInfo;
LevelBoundsTracker val = ((playerInfo != null) ? playerInfo.LevelBoundsTracker : null);
ManualLogSource log = Plugin.Log;
string[] obj = new string[12]
{
"[BubbleBoi] player=",
((playerInfo != null) ? ((Object)playerInfo).name : null) ?? ((Object)movement).name,
" ",
$"local={((NetworkBehaviour)movement).isLocalPlayer} shield={playerInfo != null && playerInfo.IsElectromagnetShieldActive} ",
$"grounded={movement.IsGrounded} visible={movement.IsVisible} ",
null,
null,
null,
null,
null,
null,
null
};
int num;
if (playerInfo == null)
{
num = 0;
}
else
{
GolfCartSeat activeGolfCartSeat = playerInfo.ActiveGolfCartSeat;
num = (((GolfCartSeat)(ref activeGolfCartSeat)).IsValid() ? 1 : 0);
}
obj[5] = $"inCart={(byte)num != 0} ";
obj[6] = "bounds=";
object obj2;
if (!((Object)(object)val != (Object)null))
{
obj2 = "null";
}
else
{
BoundsState authoritativeBoundsState = val.AuthoritativeBoundsState;
obj2 = ((object)(BoundsState)(ref authoritativeBoundsState)).ToString();
}
obj[7] = (string)obj2;
obj[8] = " waterY=";
obj[9] = (((Object)(object)val != (Object)null) ? val.CurrentOutOfBoundsHazardWorldHeightLocalOnly.ToString("F3") : "n/a");
obj[10] = " ";
obj[11] = $"posY={movement.Position.y:F3} :: {message}";
log.LogInfo((object)string.Concat(obj));
}
}
private static bool IsWaterHazard(LevelBoundsTracker tracker, BoundsState boundsState)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Invalid comparison between Unknown and I4
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
if ((Object)(object)tracker == (Object)null)
{
return false;
}
if (BoundsStateExtensions.HasState(boundsState, (BoundsState)1))
{
return (int)MainOutOfBoundsHazard.Type == 0;
}
if ((Object)(object)tracker.CurrentSecondaryHazardLocalOnly != (Object)null)
{
return (int)tracker.CurrentSecondaryHazardLocalOnly.Type == 0;
}
return (int)MainOutOfBoundsHazard.Type == 0;
}
}
}