using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.GABRlEL.BetterPreplacedPitons")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.github.GABRlEL.BetterPreplacedPitons")]
[assembly: AssemblyTitle("BetterPreplacedPitons")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BetterPreplacedPitons
{
[BepInPlugin("com.github.GABRlEL.BetterPreplacedPitons", "BetterPreplacedPitons", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
private Harmony? _harmony;
public const string Id = "com.github.GABRlEL.BetterPreplacedPitons";
internal static ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> EnablePreplacedPitons { get; private set; }
internal static ConfigEntry<bool> EnableMesaPickaxes { get; private set; }
internal static ConfigEntry<float> PreplacedPitonBreakSpeedMultiplier { get; private set; }
internal static ConfigEntry<float> MesaPickaxeBreakSpeedMultiplier { get; private set; }
internal static ConfigEntry<bool> ClientSidePersistence { get; private set; }
public static string Name => "BetterPreplacedPitons";
public static string Version => "0.1.0";
private void Awake()
{
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
EnablePreplacedPitons = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnablePreplacedPitons", true, "If true, applies the configured break-speed behavior to preplaced rope pitons (BreakableRopeAnchor).");
PreplacedPitonBreakSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PreplacedPitonBreakSpeedMultiplier", -1f, "Break-speed multiplier for preplaced rope pitons.\n <= 0 : unbreakable (default)\n 1.0 : vanilla\n 0.5 : 50% slower (lasts 2x longer)\n 2.0 : 2x faster");
EnableMesaPickaxes = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMesaPickaxes", true, "If true, applies the configured break-speed behavior to mesa pickaxes (ShittyPiton).");
MesaPickaxeBreakSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MesaPickaxeBreakSpeedMultiplier", -1f, "Break-speed multiplier for mesa pickaxes (ShittyPiton). Same meaning as the piton multiplier.");
ClientSidePersistence = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "ClientSidePersistence", false, "OFF (default) = multiplayer-safe: this mod respects break/detach RPCs from the host/owner.\nON = client-side persistence: ignore host break/detach RPCs locally and keep those objects alive on your client.\n⚠ This will desync you from other players on purpose.");
_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
_harmony.PatchAll();
BreakableRopeAnchorPatches.ApplyToAllExisting();
ShittyPitonPatches.ApplyToAllExisting();
Log.LogInfo((object)("Loaded " + Name + "! " + $"Pitons: enabled={EnablePreplacedPitons.Value}, mult={PreplacedPitonBreakSpeedMultiplier.Value}. " + $"Pickaxes: enabled={EnableMesaPickaxes.Value}, mult={MesaPickaxeBreakSpeedMultiplier.Value}. " + $"ClientSidePersistence={ClientSidePersistence.Value}"));
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
_harmony = null;
}
internal static float GetMultiplier(bool enabled, float mult)
{
if (!enabled)
{
return float.NaN;
}
if (float.IsNaN(mult) || float.IsInfinity(mult))
{
return -1f;
}
if (mult <= 0f)
{
return -1f;
}
return mult;
}
}
[HarmonyPatch(typeof(BreakableRopeAnchor))]
internal static class BreakableRopeAnchorPatches
{
private static FieldInfo? _willBreakInTime;
private static FieldInfo? _photonView;
private static FieldInfo? _anchor;
private static FieldInfo? _isBreaking;
private static void EnsureFields()
{
if ((object)_willBreakInTime == null)
{
_willBreakInTime = AccessTools.Field(typeof(BreakableRopeAnchor), "willBreakInTime");
}
if ((object)_photonView == null)
{
_photonView = AccessTools.Field(typeof(BreakableRopeAnchor), "photonView");
}
if ((object)_anchor == null)
{
_anchor = AccessTools.Field(typeof(BreakableRopeAnchor), "anchor");
}
if ((object)_isBreaking == null)
{
_isBreaking = AccessTools.Field(typeof(BreakableRopeAnchor), "isBreaking");
}
}
internal static void ApplyToAllExisting()
{
BreakableRopeAnchor[] array = Resources.FindObjectsOfTypeAll<BreakableRopeAnchor>();
foreach (BreakableRopeAnchor inst in array)
{
EnforceUnbreakableIfConfigured(inst);
}
}
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void StartPostfix(BreakableRopeAnchor __instance)
{
EnforceUnbreakableIfConfigured(__instance);
}
[HarmonyPrefix]
[HarmonyPatch("Update")]
private static void UpdatePrefix(BreakableRopeAnchor __instance)
{
EnsureFields();
if (_willBreakInTime == null || _photonView == null || _anchor == null)
{
return;
}
float multiplier = Plugin.GetMultiplier(Plugin.EnablePreplacedPitons.Value, Plugin.PreplacedPitonBreakSpeedMultiplier.Value);
if (float.IsNaN(multiplier))
{
return;
}
object? value = _photonView.GetValue(__instance);
PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
bool flag = (Object)(object)val != (Object)null && val.IsMine;
if (multiplier < 0f)
{
if (flag)
{
_willBreakInTime.SetValue(__instance, float.PositiveInfinity);
if (_isBreaking != null && (bool)_isBreaking.GetValue(__instance))
{
((MonoBehaviour)__instance).StopAllCoroutines();
_isBreaking.SetValue(__instance, false);
}
}
}
else
{
if (!flag || Mathf.Approximately(multiplier, 1f))
{
return;
}
object? value2 = _anchor.GetValue(__instance);
RopeAnchorWithRope val2 = (RopeAnchorWithRope)((value2 is RopeAnchorWithRope) ? value2 : null);
if ((Object)(object)val2?.rope == (Object)null)
{
return;
}
int num = 0;
List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
for (int i = 0; i < allPlayerCharacters.Count; i++)
{
Character val3 = allPlayerCharacters[i];
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.data != (Object)null && val3.data.isRopeClimbing && (Object)(object)val3.data.heldRope == (Object)(object)val2.rope)
{
num++;
}
}
if (num > 0)
{
float num2 = (float)_willBreakInTime.GetValue(__instance);
num2 += Time.deltaTime * (1f - multiplier);
_willBreakInTime.SetValue(__instance, num2);
}
}
}
private static void EnforceUnbreakableIfConfigured(BreakableRopeAnchor inst)
{
EnsureFields();
if (_willBreakInTime == null || _photonView == null)
{
return;
}
float multiplier = Plugin.GetMultiplier(Plugin.EnablePreplacedPitons.Value, Plugin.PreplacedPitonBreakSpeedMultiplier.Value);
if (!float.IsNaN(multiplier) && multiplier < 0f)
{
object? value = _photonView.GetValue(inst);
PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
if ((Object)(object)val != (Object)null && val.IsMine)
{
_willBreakInTime.SetValue(inst, float.PositiveInfinity);
}
}
}
}
[HarmonyPatch(typeof(ShittyPiton))]
internal static class ShittyPitonPatches
{
private static FieldInfo? _totalSecondsOfHang;
private static FieldInfo? _sinceCrack;
private static FieldInfo? _isHung;
private static FieldInfo? _isBreaking;
private static FieldInfo? _disabled;
private static FieldInfo? _crackScale;
private static FieldInfo? _cracksToBreak;
private static FieldInfo? _view;
private static FieldInfo? _handle;
private static void EnsureFields()
{
if ((object)_totalSecondsOfHang == null)
{
_totalSecondsOfHang = AccessTools.Field(typeof(ShittyPiton), "totalSecondsOfHang");
}
if ((object)_sinceCrack == null)
{
_sinceCrack = AccessTools.Field(typeof(ShittyPiton), "sinceCrack");
}
if ((object)_isHung == null)
{
_isHung = AccessTools.Field(typeof(ShittyPiton), "isHung");
}
if ((object)_isBreaking == null)
{
_isBreaking = AccessTools.Field(typeof(ShittyPiton), "isBreaking");
}
if ((object)_disabled == null)
{
_disabled = AccessTools.Field(typeof(ShittyPiton), "disabled");
}
if ((object)_crackScale == null)
{
_crackScale = AccessTools.Field(typeof(ShittyPiton), "crackScale");
}
if ((object)_cracksToBreak == null)
{
_cracksToBreak = AccessTools.Field(typeof(ShittyPiton), "cracksToBreak");
}
if ((object)_view == null)
{
_view = AccessTools.Field(typeof(ShittyPiton), "view");
}
if ((object)_handle == null)
{
_handle = AccessTools.Field(typeof(ShittyPiton), "handle");
}
}
internal static void ApplyToAllExisting()
{
ShittyPiton[] array = Resources.FindObjectsOfTypeAll<ShittyPiton>();
foreach (ShittyPiton inst in array)
{
EnforceUnbreakableIfConfigured(inst);
}
}
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void StartPostfix(ShittyPiton __instance)
{
EnforceUnbreakableIfConfigured(__instance);
}
[HarmonyPrefix]
[HarmonyPatch("Update")]
private static void UpdatePrefix(ShittyPiton __instance)
{
EnsureFields();
if (_totalSecondsOfHang == null || _sinceCrack == null || _isHung == null || _isBreaking == null || _view == null)
{
return;
}
float multiplier = Plugin.GetMultiplier(Plugin.EnableMesaPickaxes.Value, Plugin.MesaPickaxeBreakSpeedMultiplier.Value);
if (float.IsNaN(multiplier))
{
return;
}
object? value = _view.GetValue(__instance);
PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
bool flag = (Object)(object)val != (Object)null && val.IsMine;
if (multiplier < 0f)
{
if (flag)
{
_totalSecondsOfHang.SetValue(__instance, float.PositiveInfinity);
}
_isBreaking.SetValue(__instance, false);
if (_disabled != null)
{
_disabled.SetValue(__instance, false);
}
if (_crackScale != null)
{
_crackScale.SetValue(__instance, 0f);
}
if (_sinceCrack != null)
{
_sinceCrack.SetValue(__instance, 0f);
}
if (_cracksToBreak != null)
{
_cracksToBreak.SetValue(__instance, 4);
}
try
{
if ((Object)(object)__instance.crack != (Object)null && __instance.crack.activeSelf)
{
__instance.crack.SetActive(false);
}
return;
}
catch
{
return;
}
}
if (Mathf.Approximately(multiplier, 1f))
{
return;
}
bool flag2 = (bool)_isHung.GetValue(__instance);
bool flag3 = (bool)_isBreaking.GetValue(__instance);
float deltaTime = Time.deltaTime;
if (flag3)
{
if (flag2)
{
float num = (float)_sinceCrack.GetValue(__instance);
num += deltaTime * (multiplier - 1f);
_sinceCrack.SetValue(__instance, num);
}
}
else if (flag && flag2)
{
float num2 = (float)_totalSecondsOfHang.GetValue(__instance);
num2 += deltaTime * (1f - multiplier);
_totalSecondsOfHang.SetValue(__instance, num2);
}
}
[HarmonyPrefix]
[HarmonyPatch("Crack")]
private static bool CrackPrefix(ShittyPiton __instance)
{
float multiplier = Plugin.GetMultiplier(Plugin.EnableMesaPickaxes.Value, Plugin.MesaPickaxeBreakSpeedMultiplier.Value);
if (float.IsNaN(multiplier) || multiplier >= 0f)
{
return true;
}
try
{
if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine)
{
return false;
}
}
catch
{
}
return true;
}
private static void EnforceUnbreakableIfConfigured(ShittyPiton inst)
{
EnsureFields();
if (_totalSecondsOfHang == null || _view == null)
{
return;
}
float multiplier = Plugin.GetMultiplier(Plugin.EnableMesaPickaxes.Value, Plugin.MesaPickaxeBreakSpeedMultiplier.Value);
if (!float.IsNaN(multiplier) && multiplier < 0f)
{
object? value = _view.GetValue(inst);
PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
if ((Object)(object)val != (Object)null && val.IsMine)
{
_totalSecondsOfHang.SetValue(inst, float.PositiveInfinity);
}
}
}
}
[HarmonyPatch]
internal static class ClientSidePersistencePatches
{
private static FieldInfo? _ropeAttachedToAnchor;
[HarmonyPrefix]
[HarmonyPatch(typeof(Rope), "Detach_Rpc")]
private static bool Rope_Detach_Rpc_Prefix(Rope __instance, float segmentLength)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Invalid comparison between Unknown and I4
if (!Plugin.ClientSidePersistence.Value)
{
return true;
}
if (!Plugin.EnablePreplacedPitons.Value)
{
return true;
}
if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine)
{
return true;
}
if ((int)__instance.attachmenState != 2)
{
return true;
}
if ((object)_ropeAttachedToAnchor == null)
{
_ropeAttachedToAnchor = AccessTools.Field(typeof(Rope), "attachedToAnchor");
}
object? obj = _ropeAttachedToAnchor?.GetValue(__instance);
RopeAnchor val = (RopeAnchor)((obj is RopeAnchor) ? obj : null);
if ((Object)(object)val == (Object)null)
{
return true;
}
if ((Object)(object)((Component)val).GetComponent<BreakableRopeAnchor>() != (Object)null)
{
return false;
}
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShittyPiton), "RPCA_StartBreaking")]
private static bool ShittyPiton_RPCA_StartBreaking_Prefix(ShittyPiton __instance)
{
if (!Plugin.ClientSidePersistence.Value)
{
return true;
}
if (!Plugin.EnableMesaPickaxes.Value)
{
return true;
}
if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine)
{
return true;
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShittyPiton), "RPCA_Break")]
private static bool ShittyPiton_RPCA_Break_Prefix(ShittyPiton __instance)
{
if (!Plugin.ClientSidePersistence.Value)
{
return true;
}
if (!Plugin.EnableMesaPickaxes.Value)
{
return true;
}
if ((Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine)
{
return true;
}
return false;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}