Decompiled source of KeeviFixes v1.0.1
KeeviFixes/KeeviFixes.dll
Decompiled 16 hours 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.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using KeeviFixes.Configuration; using KeeviFixes.Patches; using KeeviFixes.Runtime; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("KeeviFixes")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Keevi")] [assembly: AssemblyProduct("KeeviFixes")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("5f7017a7-f723-48b3-af3e-17a70caccfec")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.1.0")] namespace KeeviFixes { [BepInPlugin("com.keevi.fixes", "Keevi Fixes", "1.0.1")] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.keevi.fixes"; public const string PLUGIN_NAME = "Keevi Fixes"; public const string PLUGIN_VERSION = "1.0.1"; internal static ManualLogSource Log { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; try { ModConfig.Bind(((BaseUnityPlugin)this).Config); LogSettings(); ApplyHarmonyPatches(); } catch (Exception arg) { Log.LogError((object)string.Format("{0} failed to load and will not activate: {1}", "Keevi Fixes", arg)); return; } Log.LogInfo((object)string.Format("{0} v{1} loaded.", "Keevi Fixes", "1.0.1")); } private void OnApplicationFocus(bool hasFocus) { FocusClick.OnFocusChanged(hasFocus); } private void LogSettings() { Log.LogInfo((object)"Configuration:"); foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((BaseUnityPlugin)this).Config) { Log.LogInfo((object)$" {item.Key.Key}: {item.Value.BoxedValue}"); } } private static void ApplyHarmonyPatches() { //IL_0005: 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) Harmony val = new Harmony("com.keevi.fixes"); val.PatchAll(Assembly.GetExecutingAssembly()); foreach (MethodBase patchedMethod in val.GetPatchedMethods()) { Log.LogInfo((object)$"Patched {patchedMethod.DeclaringType}.{patchedMethod.Name}"); } } } } namespace KeeviFixes.Runtime { internal sealed class BigContainerDrinking { private const float ReturnDuration = 0.35f; private static BigContainerDrinking current; private static BigContainerDrinking returning; private readonly PickupableItem item; private readonly GoPointer holder; private readonly Vector3 bigItemLocalPos; private readonly Vector3 decolLocalPos; private readonly Quaternion bigItemLocalRot; private readonly float heldRotationOffset; private Vector3 returnStartPos; private Quaternion returnStartRot; private float returnElapsed; public static bool IsSupported => GoPointerFields.AreFound; private BigContainerDrinking(PickupableItem item, GoPointer holder) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) this.item = item; this.holder = holder; bigItemLocalPos = GoPointerFields.BigItemLocalPos.Invoke(holder); decolLocalPos = GoPointerFields.DecolLocalPos.Invoke(holder); bigItemLocalRot = GoPointerFields.BigItemLocalRot.Invoke(holder); heldRotationOffset = item.heldRotationOffset; } public static BigContainerDrinking CaptureBeforeDrinkingStep(PickupableItem item) { if (!item.big || (Object)(object)item.held == (Object)null || !ModConfig.FixBarrelsAfterDrinking.Value) { return null; } return new BigContainerDrinking(item, item.held); } public static void TrackIfTurnedSmall(PickupableItem item, BigContainerDrinking holdBefore) { if (holdBefore != null && !item.big) { current = holdBefore; } } public static void RestoreWhenDrinkingEnds(PickupableItem item, bool isDrinking) { if (!(current == null || current.item != item || isDrinking)) { BigContainerDrinking bigContainerDrinking = current; current = null; if ((Object)(object)item.held == (Object)(object)bigContainerDrinking.holder && ModConfig.FixBarrelsAfterDrinking.Value) { bigContainerDrinking.Restore(); } } } public static void EaseReturningItem(GoPointer holder) { if (returning == null || (Object)(object)returning.holder != (Object)(object)holder) { return; } if ((Object)(object)holder.GetHeldItem() != (Object)(object)returning.item || !returning.item.big) { returning = null; return; } returning.returnElapsed += Time.deltaTime; float num = returning.returnElapsed / 0.35f; if (num >= 1f) { returning = null; } else { returning.DrawBetweenDrinkingPoseAndHold(((Component)holder).transform, Mathf.Pow(1f - num, 3f)); } } private void Restore() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00ab: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)holder).transform; returnStartPos = transform.InverseTransformPoint(((Component)item).transform.position); returnStartRot = Quaternion.Inverse(transform.rotation) * ((Component)item).transform.rotation; returnElapsed = 0f; returning = this; GoPointerFields.BigItemLocalPos.Invoke(holder) = bigItemLocalPos; GoPointerFields.DecolLocalPos.Invoke(holder) = decolLocalPos; GoPointerFields.BigItemLocalRot.Invoke(holder) = bigItemLocalRot; item.heldRotationOffset = heldRotationOffset; item.big = true; } private void DrawBetweenDrinkingPoseAndHold(Transform holderTransform, float drinkingPoseWeight) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0025: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) Transform transform = ((Component)item).transform; Vector3 val = holderTransform.InverseTransformPoint(transform.position); Quaternion val2 = Quaternion.Inverse(holderTransform.rotation) * transform.rotation; transform.position = holderTransform.TransformPoint(Vector3.Lerp(val, returnStartPos, drinkingPoseWeight)); transform.rotation = holderTransform.rotation * Quaternion.Slerp(val2, returnStartRot, drinkingPoseWeight); } } internal static class BoatWalls { private const float TargetMargin = 0.03f; private static readonly RaycastHit[] Hits; private static readonly int WallMask; public static bool IsSupported { get; } static BoatWalls() { Hits = (RaycastHit[])(object)new RaycastHit[16]; int num = LayerMask.NameToLayer("WalkCols"); IsSupported = num >= 0; WallMask = (IsSupported ? ((1 << num) | 1) : 0); } public static ShipItem ItemFrom(Collider collider) { if ((Object)(object)collider == (Object)null) { return null; } if (((Component)collider).CompareTag("ItemSubcollider") && (Object)(object)((Component)collider).transform.parent != (Object)null) { collider = ((Component)((Component)collider).transform.parent).GetComponent<Collider>(); } if (!((Object)(object)collider != (Object)null)) { return null; } return ((Component)collider).GetComponent<ShipItem>(); } public static bool FindWall(Vector3 origin, Vector3 point, ShipItem item, out RaycastHit wall) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) wall = default(RaycastHit); float nearest = float.MaxValue; Transform currentActualBoat = item.currentActualBoat; Transform currentWalkCol = item.currentWalkCol; if ((Object)(object)currentActualBoat != (Object)null && (Object)(object)currentWalkCol != (Object)null) { FindWallOnBoat(currentActualBoat, currentWalkCol, origin, point, ref wall, ref nearest); } Transform currentBoat = GameState.currentBoat; Transform val = PlayerWalkCol(); if ((Object)(object)val != (Object)null && ((Object)(object)currentBoat != (Object)(object)currentActualBoat || (Object)(object)val != (Object)(object)currentWalkCol)) { FindWallOnBoat(currentBoat, val, origin, point, ref wall, ref nearest); } return nearest < float.MaxValue; } private static Transform PlayerWalkCol() { Transform currentBoat = GameState.currentBoat; if ((Object)(object)currentBoat == (Object)null || (Object)(object)Refs.charController == (Object)null || (Object)(object)Refs.observerMirror == (Object)null || (Object)(object)((Component)Refs.observerMirror).transform.parent != (Object)(object)currentBoat) { return null; } Transform parent = ((Component)Refs.charController).transform.parent; if (!((Object)(object)parent != (Object)null) || !((Object)(object)parent != (Object)(object)currentBoat) || !((Object)(object)parent != (Object)(object)Refs.shiftingWorld)) { return null; } return parent; } private static void FindWallOnBoat(Transform boat, Transform walk, Vector3 origin, Vector3 point, ref RaycastHit wall, ref float nearest) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_000d: 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_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) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0039: 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_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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = walk.TransformPoint(boat.InverseTransformPoint(origin)); Vector3 val2 = walk.TransformPoint(boat.InverseTransformPoint(point)) - val; float num = ((Vector3)(ref val2)).magnitude - 0.03f; if (num <= 0f) { return; } int num2 = Physics.RaycastNonAlloc(val, ((Vector3)(ref val2)).normalized, Hits, num, WallMask, (QueryTriggerInteraction)1); for (int i = 0; i < num2; i++) { RaycastHit val3 = Hits[i]; if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && ((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(walk)) { Vector3 val4 = boat.TransformPoint(walk.InverseTransformPoint(((RaycastHit)(ref val3)).point)); float num3 = Vector3.Distance(origin, val4); if (!(num3 >= nearest)) { nearest = num3; ((RaycastHit)(ref val3)).point = val4; ((RaycastHit)(ref val3)).normal = boat.TransformDirection(walk.InverseTransformDirection(((RaycastHit)(ref val3)).normal)); ((RaycastHit)(ref val3)).distance = num3; wall = val3; } } } } } internal sealed class CenteredBigItemRotation { private static readonly Dictionary<GoPointer, CenteredBigItemRotation> TrackedByHolder = new Dictionary<GoPointer, CenteredBigItemRotation>(); private readonly PickupableItem item; private readonly Vector3 pivotToCenter; private Quaternion rotationInHand; public static bool IsSupported => GoPointerFields.AreFound; private CenteredBigItemRotation(PickupableItem item, Vector3 pivotToCenter, Quaternion rotationInHand) { //IL_000e: 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_0015: 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) this.item = item; this.pivotToCenter = pivotToCenter; this.rotationInHand = rotationInHand; } public static void KeepHeldItemCentered(GoPointer holder) { PickupableItem heldItem = holder.GetHeldItem(); CenteredBigItemRotation value; if ((Object)(object)heldItem == (Object)null || !heldItem.big || !ModConfig.FixRotationCenter.Value) { TrackedByHolder.Remove(holder); } else if (TrackedByHolder.TryGetValue(holder, out value) && (Object)(object)value.item == (Object)(object)heldItem) { value.PivotAroundCenter(holder); } else { StartTracking(holder, heldItem); } } private static void StartTracking(GoPointer holder, PickupableItem heldItem) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) ForgetDestroyedHolders(); TrackedByHolder[holder] = new CenteredBigItemRotation(heldItem, MeasurePivotToCenter(heldItem), ReadRotationInHand(holder, heldItem)); } private static void ForgetDestroyedHolders() { foreach (GoPointer item in TrackedByHolder.Keys.Where((GoPointer holder) => (Object)(object)holder == (Object)null).ToList()) { TrackedByHolder.Remove(item); } } private void PivotAroundCenter(GoPointer holder) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) Quaternion val = ReadRotationInHand(holder, item); if (!((Quaternion)(ref val)).Equals(rotationInHand)) { Vector3 val2 = rotationInHand * pivotToCenter - val * pivotToCenter; rotationInHand = val; MoveHeldItem(holder, ((Component)holder).transform.rotation * val2); } } private void MoveHeldItem(GoPointer holder, Vector3 worldShift) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0056: 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) Vector3 val = ((Component)holder).transform.InverseTransformVector(worldShift); ref Vector3 reference = ref GoPointerFields.BigItemLocalPos.Invoke(holder); reference += val; ref Vector3 reference2 = ref GoPointerFields.DecolLocalPos.Invoke(holder); reference2 += val; Transform transform = ((Component)item).transform; transform.position += worldShift; } private static Quaternion ReadRotationInHand(GoPointer holder, PickupableItem heldItem) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) return Quaternion.AngleAxis(heldItem.heldRotationOffset, Vector3.right) * GoPointerFields.BigItemLocalRot.Invoke(holder); } private static Vector3 MeasurePivotToCenter(PickupableItem heldItem) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0030: 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_003a: 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) if (!TryGetRenderedBounds(heldItem, out var boundsInItem)) { return Vector3.zero; } Transform transform = ((Component)heldItem).transform; return Quaternion.Inverse(transform.rotation) * (transform.TransformPoint(((Bounds)(ref boundsInItem)).center) - transform.position); } private static bool TryGetRenderedBounds(PickupableItem heldItem, out Bounds boundsInItem) { //IL_0001: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0077: Unknown result type (might be due to invalid IL or missing references) boundsInItem = default(Bounds); bool flag = false; Matrix4x4 worldToLocalMatrix = ((Component)heldItem).transform.worldToLocalMatrix; MeshFilter[] componentsInChildren = ((Component)heldItem).GetComponentsInChildren<MeshFilter>(); foreach (MeshFilter val in componentsInChildren) { if (!IsRendered(val)) { continue; } Matrix4x4 val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; foreach (Vector3 corner in GetCorners(val.sharedMesh.bounds)) { Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(corner); if (flag) { ((Bounds)(ref boundsInItem)).Encapsulate(val3); } else { boundsInItem = new Bounds(val3, Vector3.zero); } flag = true; } } return flag; } private static bool IsRendered(MeshFilter meshFilter) { MeshRenderer component = ((Component)meshFilter).GetComponent<MeshRenderer>(); if ((Object)(object)meshFilter.sharedMesh != (Object)null && (Object)(object)component != (Object)null) { return ((Renderer)component).enabled; } return false; } private static IEnumerable<Vector3> GetCorners(Bounds bounds) { //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) Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; yield return new Vector3(min.x, min.y, min.z); yield return new Vector3(min.x, min.y, max.z); yield return new Vector3(min.x, max.y, min.z); yield return new Vector3(min.x, max.y, max.z); yield return new Vector3(max.x, min.y, min.z); yield return new Vector3(max.x, min.y, max.z); yield return new Vector3(max.x, max.y, min.z); yield return new Vector3(max.x, max.y, max.z); } } internal static class CutPieces { private struct Box { public readonly Vector3 Center; public readonly Vector3 Size; public Box(Vector3 center, Vector3 size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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) Center = center; Size = size; } public float Extent(Transform transform, Vector3 direction) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_001f: 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_003d: Unknown result type (might be due to invalid IL or missing references) return Mathf.Abs(Vector3.Dot(direction, transform.right)) * Size.x + Mathf.Abs(Vector3.Dot(direction, transform.up)) * Size.y + Mathf.Abs(Vector3.Dot(direction, transform.forward)) * Size.z; } } private struct Shape { public readonly Vector3 Center; public readonly Vector3 Axis; public readonly float HalfHeight; public Shape(Vector3 center, Vector3 axis, float halfHeight) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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) Center = center; Axis = axis; HalfHeight = halfHeight; } } private const float PieceGap = 0.01f; private const float GameSpacing = 0.02f; private const float MaxLevelAxisSlope = 0.7f; private const float SameDirectionTolerance = 0.1f; private static readonly List<Transform> Pieces = new List<Transform>(); private static ShipItem cutItem; private static ShipItemKnife knife; private static bool loggedFailure; public static void BeforeCut(ShipItemKnife cuttingKnife) { Pieces.Clear(); cutItem = null; knife = cuttingKnife; if (!((Object)(object)((PickupableItem)cuttingKnife).held == (Object)null) && ModConfig.FixCutPiecePlacement.Value) { ShipItem pointedAtItem = ((PickupableItem)cuttingKnife).held.GetPointedAtItem(); if ((Object)(object)pointedAtItem != (Object)null && pointedAtItem.sold) { cutItem = pointedAtItem; } } } public static void OnRegistered(SaveablePrefab prefab) { if (!((Object)(object)cutItem == (Object)null) && !((Object)(object)prefab == (Object)null) && !((Object)(object)((Component)prefab).gameObject == (Object)(object)((Component)cutItem).gameObject) && !((Object)(object)((Component)prefab).gameObject == (Object)(object)((Component)knife).gameObject) && !Pieces.Contains(((Component)prefab).transform)) { Pieces.Add(((Component)prefab).transform); } } public static void AfterCut() { try { if ((Object)(object)cutItem != (Object)null && Pieces.Count > 0) { Place(); } } catch (Exception ex) { if (!loggedFailure) { loggedFailure = true; Plugin.Log.LogError((object)("Could not place the pieces of a cut item; they keep the game's places: " + ex)); } } finally { Pieces.Clear(); cutItem = null; knife = null; } } private static void Place() { //IL_0050: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0139: 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_0145: 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) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) Transform template = FirstWithBox(); Shape shape = ShapeOf(cutItem, template); float num = 0f; float num2 = 0f; foreach (Transform piece in Pieces) { if (!((Object)(object)piece == (Object)null) && TryGetBox(piece, out var box)) { num = Mathf.Max(num, box.Extent(piece, shape.Axis)); num2 = Mathf.Max(num2, box.Extent(piece, Vector3.up) * 0.5f); } } float num3 = ((num > 0f) ? (num + 0.01f) : 0.02f); Vector3 val = shape.Center + Vector3.up * Mathf.Max(0f, num2 - shape.HalfHeight); for (int i = 0; i < Pieces.Count; i++) { Transform val2 = Pieces[i]; if (!((Object)(object)val2 == (Object)null)) { Vector3 val3 = val + shape.Axis * (((float)i - (float)(Pieces.Count - 1) * 0.5f) * num3); Box box2; Vector3 val4 = (TryGetBox(val2, out box2) ? (val2.TransformPoint(box2.Center) - val2.position) : Vector3.zero); val2.position = val3 - val4; } } } private static Transform FirstWithBox() { foreach (Transform piece in Pieces) { if ((Object)(object)piece != (Object)null && TryGetBox(piece, out var _)) { return piece; } } return null; } private static Shape ShapeOf(ShipItem item, Transform template) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0012: 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) Transform transform = ((Component)item).transform; if (!TryGetBox(transform, out var box)) { return new Shape(transform.position, transform.right, 0f); } Vector3[] array = (Vector3[])(object)new Vector3[3] { transform.right, transform.up, transform.forward }; int num = SpreadAxis(box.Size, array, PieceLength(template)); return new Shape(transform.TransformPoint(box.Center), array[num], box.Extent(transform, Vector3.up) * 0.5f); } private static int SpreadAxis(Vector3 size, Vector3[] directions, Vector3 pieceLength) { //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) //IL_0044: 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) int num = 0; int num2 = -1; float num3 = float.MaxValue; for (int i = 0; i < 3; i++) { if (((Vector3)(ref size))[i] > ((Vector3)(ref size))[num]) { num = i; } if (!(Mathf.Abs(Vector3.Dot(directions[i], Vector3.up)) >= 0.7f)) { float num4 = Mathf.Abs(Vector3.Dot(directions[i], ((Vector3)(ref pieceLength)).normalized)); bool flag = num4 < num3 - 0.1f; bool flag2 = num2 >= 0 && Mathf.Abs(num4 - num3) <= 0.1f && ((Vector3)(ref size))[i] > ((Vector3)(ref size))[num2]; if (num2 < 0 || flag || flag2) { num2 = i; num3 = num4; } } } if (num2 < 0) { return num; } return num2; } private static Vector3 PieceLength(Transform piece) { //IL_0013: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece == (Object)null || !TryGetBox(piece, out var box)) { return Vector3.zero; } Vector3 size = box.Size; return (Vector3)(((!(size.x >= size.y) || !(size.x >= size.z)) ? ((size.y >= size.z) ? 1 : 2) : 0) switch { 1 => piece.up, 0 => piece.right, _ => piece.forward, }); } private static bool TryGetBox(Transform transform, out Box box) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_00d5: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b1: 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_00be: 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) BoxCollider component = ((Component)transform).GetComponent<BoxCollider>(); CapsuleCollider component2 = ((Component)transform).GetComponent<CapsuleCollider>(); MeshCollider component3 = ((Component)transform).GetComponent<MeshCollider>(); Vector3 center; Vector3 val; if ((Object)(object)component != (Object)null) { center = component.center; val = component.size; } else if ((Object)(object)component2 != (Object)null) { center = component2.center; val = Vector3.one * component2.radius * 2f; ((Vector3)(ref val))[component2.direction] = Mathf.Max(component2.height, component2.radius * 2f); } else { if (!((Object)(object)component3 != (Object)null) || !((Object)(object)component3.sharedMesh != (Object)null)) { box = default(Box); return false; } Bounds bounds = component3.sharedMesh.bounds; center = ((Bounds)(ref bounds)).center; bounds = component3.sharedMesh.bounds; val = ((Bounds)(ref bounds)).size; } Vector3 val2 = Vector3.Scale(val, transform.lossyScale); box = new Box(center, new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z))); return true; } } internal static class FocusClick { private const float FocusClickWindow = 0.15f; private const int MouseButtonCount = 7; private static readonly bool[] Swallowed = new bool[7]; private static readonly Func<KeyCode, bool> KeyDown = Input.GetKeyDown; private static readonly Func<KeyCode, bool> Key = Input.GetKey; private static readonly Func<KeyCode, bool> KeyUp = Input.GetKeyUp; private static float focusTime = float.NegativeInfinity; private static int refreshedFrame = -1; private static int swallowedCount; public static bool IsSwallowing { get { Refresh(); return swallowedCount > 0; } } public static void OnFocusChanged(bool focused) { if (!focused) { return; } focusTime = Time.realtimeSinceStartup; refreshedFrame = -1; for (int i = 0; i < 7; i++) { if (Input.GetKey((KeyCode)(323 + i))) { Swallow(i); } } } public static bool GetKeyDown(InputName inputName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Read(inputName, KeyDown); } public static bool GetKey(InputName inputName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Read(inputName, Key); } public static bool GetKeyUp(InputName inputName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Read(inputName, KeyUp); } public static bool GetMouseButtonDown(int button) { if (Input.GetMouseButtonDown(button)) { return !IsSwallowed((KeyCode)(323 + button)); } return false; } public static bool GetMouseButton(int button) { if (Input.GetMouseButton(button)) { return !IsSwallowed((KeyCode)(323 + button)); } return false; } public static bool GetMouseButtonUp(int button) { if (Input.GetMouseButtonUp(button)) { return !IsSwallowed((KeyCode)(323 + button)); } return false; } private static bool Read(InputName inputName, Func<KeyCode, bool> read) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_0013: 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_0023: Unknown result type (might be due to invalid IL or missing references) if (!ReadKey(GameInput.GetKeyCode(inputName, false, false), read) && !ReadKey(GameInput.GetKeyCode(inputName, true, false), read)) { if (ReadKey(GameInput.GetKeyCode(inputName, false, true), read)) { return GameInput.controllerEnabled; } return false; } return true; } private static bool ReadKey(KeyCode key, Func<KeyCode, bool> read) { //IL_0001: 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) if (read(key)) { return !IsSwallowed(key); } return false; } private static bool IsSwallowed(KeyCode key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected I4, but got Unknown Refresh(); int num = key - 323; if (num >= 0 && num < 7) { return Swallowed[num]; } return false; } private static void Refresh() { //IL_004b: 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_007e: 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) int frameCount = Time.frameCount; if (frameCount == refreshedFrame) { return; } refreshedFrame = frameCount; bool flag = Time.realtimeSinceStartup - focusTime <= 0.15f && ModConfig.FixFocusClick.Value; if (swallowedCount == 0 && !flag) { return; } for (int i = 0; i < 7; i++) { KeyCode val = (KeyCode)(323 + i); if (Swallowed[i]) { if (!Input.GetKey(val) && !Input.GetKeyUp(val)) { Swallowed[i] = false; swallowedCount--; } } else if (flag && Input.GetKeyDown(val)) { Swallow(i); } } } private static void Swallow(int button) { if (!Swallowed[button] && ModConfig.FixFocusClick.Value) { Swallowed[button] = true; swallowedCount++; } } } internal static class FurnitureReach { private const int LookLayers = -604165; private const float LookDistance = 1.8f; private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[32]; private static readonly Type[] NoArguments = new Type[0]; private static readonly Type[] PointerArgument = new Type[1] { typeof(GoPointer) }; private static readonly Type[] HitArgument = new Type[1] { typeof(RaycastHit) }; private static readonly Dictionary<Type, bool> OwnClickByType = new Dictionary<Type, bool>(); private static GoPointer outliningPointer; private static ShipItem outlinedItem; private static ShipItem outlinedFurniture; public static void AfterLook(GoPointer pointer, PickupableItem heldItem, Ray ray, RaycastHit hit, ref GoPointerButton pointedAtButton, ref float currentLookDistance) { //IL_005e: 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_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)outliningPointer == (Object)(object)pointer) { outliningPointer = null; } if ((Object)(object)heldItem != (Object)null || !ModConfig.FixReachingBehindFurniture.Value || !GameAims(pointer)) { return; } ShipItem val = NailedOwner(((RaycastHit)(ref hit)).collider); if ((Object)(object)val == (Object)null || ((Object)(object)pointedAtButton != (Object)null && (Object)(object)pointedAtButton != (Object)(object)val)) { return; } RaycastHit itemHit; ShipItem val2 = FindItemBehind(ray, out itemHit); if ((Object)(object)val2 == (Object)null || (BoatWalls.IsSupported && ModConfig.FixReachingThroughWalls.Value && BoatWalls.FindWall(((Ray)(ref ray)).origin, ((RaycastHit)(ref itemHit)).point, val2, out var _))) { return; } if ((Object)(object)pointedAtButton == (Object)null) { pointedAtButton = (GoPointerButton)(object)val2; currentLookDistance = ((RaycastHit)(ref itemHit)).distance; ((GoPointerButton)val2).Look(pointer); } else if (!HasOwnClick(val)) { ((GoPointerButton)val2).Look(pointer); if (!((GoPointerButton)val).IsCliked()) { ((GoPointerButton)val).ForceUnlook(); } outliningPointer = pointer; outlinedItem = val2; outlinedFurniture = val; } } public static void BeforeClicks(GoPointer pointer, PickupableItem heldItem, ref GoPointerButton pointedAtButton) { if (!((Object)(object)outliningPointer != (Object)(object)pointer) && !((Object)(object)heldItem != (Object)null) && !((Object)(object)outlinedItem == (Object)null) && !((Object)(object)pointedAtButton != (Object)(object)outlinedFurniture) && !((Object)(object)((PickupableItem)outlinedItem).held != (Object)null) && pointer.MainButtonDown()) { pointedAtButton = (GoPointerButton)(object)outlinedItem; } } private static bool GameAims(GoPointer pointer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)pointer.type == 2 && GameState.inCursorMenu) { return false; } if (!GameState.sleeping && !Object.op_Implicit((Object)(object)GameState.inBed)) { return !BoatCamera.on; } return false; } private static ShipItem NailedOwner(Collider collider) { if ((Object)(object)collider == (Object)null) { return null; } if (((Component)collider).CompareTag("ItemSubcollider") && (Object)(object)((Component)collider).transform.parent != (Object)null) { collider = ((Component)((Component)collider).transform.parent).GetComponent<Collider>(); } if ((Object)(object)collider == (Object)null) { return null; } ShipItem val = ((Component)collider).GetComponent<ShipItem>(); if ((Object)(object)val == (Object)null) { if ((Object)(object)((Component)collider).GetComponent<GoPointerButton>() != (Object)null || (Object)(object)((Component)collider).transform.parent == (Object)null) { return null; } val = ((Component)((Component)collider).transform.parent).GetComponentInParent<ShipItem>(); } if (!((Object)(object)val != (Object)null) || !val.nailed) { return null; } return val; } private static ShipItem FindItemBehind(Ray ray, out RaycastHit itemHit) { //IL_0001: 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_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) itemHit = default(RaycastHit); int num = Physics.RaycastNonAlloc(ray, Hits, 1.8f, LookRayPatch.ReachableLayers(-604165)); SortByDistance(num); for (int i = 0; i < num; i++) { Collider collider = ((RaycastHit)(ref Hits[i])).collider; if (!((Object)(object)collider == (Object)null) && !((Object)(object)NailedOwner(collider) != (Object)null)) { ShipItem val = BoatWalls.ItemFrom(collider); if ((Object)(object)val == (Object)null || ((PickupableItem)val).big || val.nailed || ((GoPointerButton)val).unclickable || (Object)(object)((PickupableItem)val).held != (Object)null) { return null; } itemHit = Hits[i]; return val; } } return null; } private static void SortByDistance(int count) { //IL_000a: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) for (int i = 1; i < count; i++) { RaycastHit val = Hits[i]; int num = i - 1; while (num >= 0 && ((RaycastHit)(ref Hits[num])).distance > ((RaycastHit)(ref val)).distance) { Hits[num + 1] = Hits[num]; num--; } Hits[num + 1] = val; } } private static bool HasOwnClick(ShipItem furniture) { Type type = ((object)furniture).GetType(); if (!OwnClickByType.TryGetValue(type, out var value)) { value = Overrides(type, "OnActivate", NoArguments) || Overrides(type, "OnActivate", PointerArgument) || Overrides(type, "OnActivateHit", HitArgument); OwnClickByType[type] = value; } return value; } private static bool Overrides(Type type, string name, Type[] arguments) { MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, arguments, null); if (method != null) { return method.DeclaringType != typeof(GoPointerButton); } return false; } } internal static class GoPointerFields { public static readonly FieldRef<GoPointer, Vector3> BigItemLocalPos = Find<Vector3>("bigItemLocalPos"); public static readonly FieldRef<GoPointer, Vector3> DecolLocalPos = Find<Vector3>("decolLocalPos"); public static readonly FieldRef<GoPointer, Quaternion> BigItemLocalRot = Find<Quaternion>("bigItemLocalRot"); public static bool AreFound { get { if (BigItemLocalPos != null && DecolLocalPos != null) { return BigItemLocalRot != null; } return false; } } private static FieldRef<GoPointer, T> Find<T>(string name) { FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name); if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(T))) { return null; } return AccessTools.FieldRefAccess<GoPointer, T>(fieldInfo); } } internal static class HungItemRehang { private struct PendingHang { public readonly ShipItemLampHook Hook; public readonly Quaternion Rotation; public PendingHang(ShipItemLampHook hook, Quaternion rotation) { //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) Hook = hook; Rotation = rotation; } } private const float MatchDistance = 0.01f; private const float HangingDistance = 0.128f; private static readonly FieldRef<ShipItemLampHook, bool> Occupied = Find<ShipItemLampHook, bool>("occupied"); private static readonly List<HangableItem> LoadedItems = new List<HangableItem>(); private static readonly List<ShipItemLampHook> LoadedHooks = new List<ShipItemLampHook>(); private static readonly Dictionary<HangableItem, PendingHang> Pending = new Dictionary<HangableItem, PendingHang>(); private static bool hooksHangMoreResolved; private static IDictionary hooksHangMoreOffsets; private static MethodInfo hooksHangMorePosition; public static bool IsSupported => Occupied != null; public static void OnLoaded(SaveablePrefab prefab, SavePrefabData data) { if (data == null || data.crateId > 0 || data.inventorySlot > -1 || !ModConfig.FixHungItemsFalling.Value) { return; } ShipItemLampHook component = ((Component)prefab).GetComponent<ShipItemLampHook>(); if ((Object)(object)component != (Object)null) { LoadedHooks.Add(component); return; } HangableItem component2 = ((Component)prefab).GetComponent<HangableItem>(); if ((Object)(object)component2 != (Object)null) { LoadedItems.Add(component2); } } public static void AfterBatch() { try { if (LoadedItems.Count <= 0 || LoadedHooks.Count <= 0 || !ModConfig.FixHungItemsFalling.Value) { return; } ForgetDestroyedItems(); foreach (HangableItem loadedItem in LoadedItems) { FindHook(loadedItem); } } finally { LoadedItems.Clear(); LoadedHooks.Clear(); } } public static void BeforeFirstPhysicsStep(HangableItem item) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (Pending.Count == 0 || !Pending.TryGetValue(item, out var value)) { return; } Pending.Remove(item); ShipItem component = ((Component)item).GetComponent<ShipItem>(); if ((Object)(object)value.Hook == (Object)null || Occupied.Invoke(value.Hook) || item.IsHanging() || (Object)(object)component == (Object)null || (Object)(object)((PickupableItem)component).held != (Object)null || !ModConfig.FixHungItemsFalling.Value) { return; } Collider component2 = ((Component)value.Hook).GetComponent<Collider>(); if (!((Object)(object)component2 == (Object)null)) { item.ConnectJoint(component2); ((Component)item).transform.rotation = value.Rotation; if (item.IsHanging()) { Plugin.Log.LogInfo((object)$"Hung {((Object)item).name} back on its hook after loading."); } } } private static void FindHook(HangableItem item) { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) if ((Object)(object)item == (Object)null || item.IsHanging()) { return; } Vector3 offset = HangingOffset(item); Vector3 position = ((Component)item).transform.position; ShipItemLampHook val = null; float num = 0.01f; foreach (ShipItemLampHook loadedHook in LoadedHooks) { if (!((Object)(object)loadedHook == (Object)null) && !IsClaimed(loadedHook)) { float num2 = Vector3.Distance(position, HangingPoint(((Component)loadedHook).transform, offset)); if (!(num2 > num)) { val = loadedHook; num = num2; } } } if ((Object)(object)val != (Object)null) { Pending[item] = new PendingHang(val, ((Component)item).transform.rotation); } } private static bool IsClaimed(ShipItemLampHook hook) { foreach (PendingHang value in Pending.Values) { if ((Object)(object)value.Hook == (Object)(object)hook) { return true; } } return false; } private static void ForgetDestroyedItems() { if (Pending.Count == 0) { return; } List<HangableItem> list = new List<HangableItem>(); foreach (HangableItem key in Pending.Keys) { if ((Object)(object)key == (Object)null) { list.Add(key); } } foreach (HangableItem item in list) { Pending.Remove(item); } } private static Vector3 HangingPoint(Transform hook, Vector3 offset) { //IL_0001: 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_000c: 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_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) Vector3 result = hook.position + hook.forward * (offset.z - 0.128f) + hook.right * offset.x; result.y += offset.y; return result; } private static Vector3 HangingOffset(HangableItem item) { //IL_001e: 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) //IL_0038: Unknown result type (might be due to invalid IL or missing references) ResolveHooksHangMore(); if (hooksHangMoreOffsets == null || !hooksHangMoreOffsets.Contains(((Object)item).name)) { return Vector3.zero; } object obj = hooksHangMoreOffsets[((Object)item).name]; if (obj == null) { return Vector3.zero; } return (Vector3)hooksHangMorePosition.Invoke(obj, null); } private static void ResolveHooksHangMore() { if (hooksHangMoreResolved) { return; } hooksHangMoreResolved = true; Type type = AccessTools.TypeByName("HooksHangMore.Offsets"); if (!(type == null)) { FieldInfo fieldInfo = AccessTools.Field(type, "HangingItems"); PropertyInfo propertyInfo = AccessTools.Property(type, "Position"); IDictionary dictionary = ((fieldInfo != null && fieldInfo.IsStatic) ? (fieldInfo.GetValue(null) as IDictionary) : null); if (dictionary == null || propertyInfo == null || propertyInfo.PropertyType != typeof(Vector3)) { Plugin.Log.LogWarning((object)"Could not read the HooksHangMore hanging offsets - that mod may have updated. Its pots, mugs and other items may still fall from hooks after loading."); return; } hooksHangMoreOffsets = dictionary; hooksHangMorePosition = propertyInfo.GetGetMethod(); } } private static FieldRef<TObject, TField> Find<TObject, TField>(string name) { FieldInfo fieldInfo = AccessTools.Field(typeof(TObject), name); if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(TField))) { return null; } return AccessTools.FieldRefAccess<TObject, TField>(fieldInfo); } } internal sealed class MooredBoat : MonoBehaviour { private BoatMooringRopes boatLines; public static void AttachTo(BoatMooringRopes boatLines) { if ((Object)(object)((Component)boatLines).GetComponent<MooredBoat>() == (Object)null) { ((Component)boatLines).gameObject.AddComponent<MooredBoat>().boatLines = boatLines; } } private void OnEnable() { ((MonoBehaviour)this).StartCoroutine(AttachSpringsNextFrame()); } private IEnumerator AttachSpringsNextFrame() { yield return null; MooringRetie.AttachSprings(boatLines); } } internal static class MooringFix { private const string MooringLineFixGuid = "DogEggz.Moorlinefix"; private static bool isResolved; private static bool isAvailable; public static bool IsAvailable { get { if (!isResolved) { Resolve(); } return isAvailable; } } private static void Resolve() { isResolved = true; if (Chainloader.PluginInfos.ContainsKey("DogEggz.Moorlinefix")) { Plugin.Log.LogInfo((object)"MooringLineFix is installed, so Keevi Fixes leaves mooring lines to it."); } else if (!MooringLineFields.AreFound) { Plugin.Log.LogWarning((object)"Could not find the mooring line members - the game may have updated. Moored boats may still come loose, and mooring lines may still change their length."); } else { isAvailable = true; } } } internal static class MooringLineFields { public static readonly FieldRef<PickupableBoatMooringRope, SpringJoint> MooredSpring = Find<SpringJoint>("mooredToSpring"); public static readonly FieldRef<PickupableBoatMooringRope, Transform> HomeParent = Find<Transform>("initialParent"); public static readonly FieldRef<PickupableBoatMooringRope, bool> IsLengthDue = Find<bool>("wasKinematic"); private static readonly Func<PickupableBoatMooringRope, float> CurrentDistanceSquared = FindDistanceMeasure(); public static bool AreFound { get { if (MooredSpring != null && HomeParent != null && IsLengthDue != null) { return CurrentDistanceSquared != null; } return false; } } public static float MeasureDistance(PickupableBoatMooringRope line) { return Mathf.Sqrt(CurrentDistanceSquared(line)); } public static void SetLength(PickupableBoatMooringRope line, SpringJoint spring, float length) { spring.maxDistance = length; line.currentRopeLengthSquared = length * length; } private static FieldRef<PickupableBoatMooringRope, T> Find<T>(string name) { FieldInfo fieldInfo = AccessTools.Field(typeof(PickupableBoatMooringRope), name); if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(T))) { return null; } return AccessTools.FieldRefAccess<PickupableBoatMooringRope, T>(fieldInfo); } private static Func<PickupableBoatMooringRope, float> FindDistanceMeasure() { MethodInfo methodInfo = AccessTools.Method(typeof(PickupableBoatMooringRope), "GetCurrentDistanceSquared", (Type[])null, (Type[])null); if (!(methodInfo != null) || methodInfo.IsStatic || !(methodInfo.ReturnType == typeof(float)) || methodInfo.GetParameters().Length != 0) { return null; } return (Func<PickupableBoatMooringRope, float>)Delegate.CreateDelegate(typeof(Func<PickupableBoatMooringRope, float>), methodInfo); } } internal static class MooringLineLength { private const float Tolerance = 0.01f; public static void Remember(PickupableBoatMooringRope line) { SpringJoint val = MooringLineFields.MooredSpring.Invoke(line); if ((Object)(object)val != (Object)null && MooringFix.IsAvailable) { SetKeptLength(line, val.maxDistance); } } public static void RestoreAfterLoading(PickupableBoatMooringRope line, float savedLength) { SetKeptLength(line, savedLength); MooringLineFields.IsLengthDue.Invoke(line) = true; } public static void BeforeLineUpdate(PickupableBoatMooringRope line) { SpringJoint val = MooringLineFields.MooredSpring.Invoke(line); if ((Object)(object)val == (Object)null || !MooringFix.IsAvailable) { return; } Rigidbody boatRigidbody = line.GetBoatRigidbody(); if (!((Object)(object)boatRigidbody == (Object)null) && !boatRigidbody.isKinematic) { if (MooringLineFields.IsLengthDue.Invoke(line)) { ApplyOnWaking(line, val); } else if (ModConfig.FixMooringLineLength.Value) { TakeInSlack(line, val); } } } private static void ApplyOnWaking(PickupableBoatMooringRope line, SpringJoint spring) { float num = MooringLineFields.MeasureDistance(line); float num2 = KeptLength(line); if (!ModConfig.FixMooringLineLength.Value || num2 <= 0f) { SetKeptLength(line, num); return; } MooringLineFields.IsLengthDue.Invoke(line) = false; MooringLineFields.SetLength(line, spring, Mathf.Max(num2, num)); } private static void TakeInSlack(PickupableBoatMooringRope line, SpringJoint spring) { float num = KeptLength(line); if (!(num <= 0f) && !(spring.maxDistance <= num + 0.01f)) { float num2 = MooringLineFields.MeasureDistance(line); if (num2 < spring.maxDistance) { MooringLineFields.SetLength(line, spring, Mathf.Max(num, num2)); } } } private static float KeptLength(PickupableBoatMooringRope line) { SaveableObject component = ((Component)line).GetComponent<SaveableObject>(); if (!((Object)(object)component != (Object)null)) { return 0f; } return component.extraValue; } private static void SetKeptLength(PickupableBoatMooringRope line, float length) { SaveableObject component = ((Component)line).GetComponent<SaveableObject>(); if ((Object)(object)component != (Object)null) { component.extraValue = length; } } } internal static class MooringRetie { private struct LoadedLine { public readonly PickupableBoatMooringRope Line; public readonly float SavedLength; public LoadedLine(PickupableBoatMooringRope line, float savedLength) { Line = line; SavedLength = savedLength; } } private const float MatchDistance = 0.5f; private static readonly List<LoadedLine> LoadedLines = new List<LoadedLine>(); private static bool IsEnabled { get { if (ModConfig.FixMooredBoatsComingLoose.Value) { return MooringFix.IsAvailable; } return false; } } public static void OnLoaded(SaveableObject saveable, SaveObjectData data) { if (data != null && data.extraSetting && !((Object)(object)((Component)saveable).transform.parent != (Object)null)) { PickupableBoatMooringRope component = ((Component)saveable).GetComponent<PickupableBoatMooringRope>(); if ((Object)(object)component != (Object)null && !component.IsMoored() && IsEnabled) { LoadedLines.Add(new LoadedLine(component, data.extraValue)); } } } public static void AfterLoadGame() { try { if (LoadedLines.Count == 0 || !IsEnabled) { return; } GPButtonDockMooring[] cleats = Resources.FindObjectsOfTypeAll<GPButtonDockMooring>().Where(delegate(GPButtonDockMooring cleat) { //IL_000f: 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) if ((Object)(object)cleat != (Object)null) { Scene scene = ((Component)cleat).gameObject.scene; return ((Scene)(ref scene)).IsValid(); } return false; }).ToArray(); int num = 0; foreach (LoadedLine loadedLine in LoadedLines) { if (Retie(loadedLine, cleats)) { num++; } } Plugin.Log.LogInfo((object)$"Tied {num} of {LoadedLines.Count} loaded mooring lines back to their cleats."); } finally { LoadedLines.Clear(); } } public static void OnTied(PickupableBoatMooringRope line) { Rigidbody boatRigidbody = line.GetBoatRigidbody(); BoatMooringRopes val = (((Object)(object)boatRigidbody != (Object)null) ? ((Component)boatRigidbody).GetComponent<BoatMooringRopes>() : null); if ((Object)(object)val != (Object)null && MooringFix.IsAvailable) { MooredBoat.AttachTo(val); } } public static void AttachSprings(BoatMooringRopes boatLines) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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 (boatLines.ropes == null || !IsEnabled) { return; } Rigidbody component = ((Component)boatLines).GetComponent<Rigidbody>(); PickupableBoatMooringRope[] ropes = boatLines.ropes; foreach (PickupableBoatMooringRope val in ropes) { SpringJoint val2 = (((Object)(object)val != (Object)null) ? MooringLineFields.MooredSpring.Invoke(val) : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Joint)val2).connectedBody != (Object)(object)component)) { Vector3 connectedAnchor = ((Joint)val2).connectedAnchor; ((Joint)val2).connectedBody = null; ((Joint)val2).connectedBody = component; ((Joint)val2).connectedAnchor = connectedAnchor; } } } private static bool Retie(LoadedLine loaded, GPButtonDockMooring[] cleats) { PickupableBoatMooringRope line = loaded.Line; if ((Object)(object)line == (Object)null || line.IsMoored()) { return false; } GPButtonDockMooring val = FindCleatUnder(line, cleats); if ((Object)(object)val == (Object)null) { ReturnAboard(line); return false; } line.MoorTo(val); MooringLineLength.RestoreAfterLoading(line, loaded.SavedLength); return true; } private static GPButtonDockMooring FindCleatUnder(PickupableBoatMooringRope line, GPButtonDockMooring[] cleats) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) Vector3 position = ((Component)line).transform.position; Transform transform = ((Component)line.GetBoatRigidbody()).transform; GPButtonDockMooring result = null; float num = 0.5f; foreach (GPButtonDockMooring val in cleats) { Vector2 val2 = new Vector2(((Component)val).transform.position.x - position.x, ((Component)val).transform.position.z - position.z); float magnitude = ((Vector2)(ref val2)).magnitude; if (!(magnitude > num) && !((Component)val).transform.IsChildOf(transform) && IsFree(val)) { result = val; num = magnitude; } } return result; } private static bool IsFree(GPButtonDockMooring cleat) { if ((Object)(object)cleat.spring == (Object)null) { cleat.spring = ((Component)cleat).GetComponent<SpringJoint>(); } if ((Object)(object)cleat.spring != (Object)null) { return (Object)(object)((Joint)cleat.spring).connectedBody == (Object)null; } return false; } private static void ReturnAboard(PickupableBoatMooringRope line) { ((Component)line).transform.parent = MooringLineFields.HomeParent.Invoke(line); line.ResetRopePos(); Plugin.Log.LogWarning((object)$"Found no free cleat under the loaded mooring line {((Object)line).name} of {((Object)line.GetBoatRigidbody()).name}, so it goes back aboard."); } } } namespace KeeviFixes.Patches { internal static class BigContainerDrinkingPatches { [HarmonyPatch(typeof(ShipItemBottle))] private static class BottlePatches { private static bool Prepare() { if (!BigContainerDrinking.IsSupported) { Plugin.Log.LogWarning((object)"Could not find the GoPointer fields for held big items - the game may have updated. Barrels will stay small items after drinking until dropped."); } return BigContainerDrinking.IsSupported; } [HarmonyPrefix] [HarmonyPatch("OnAltHeld")] private static void BeforeDrinkingStep(ShipItemBottle __instance, out BigContainerDrinking __state) { __state = BigContainerDrinking.CaptureBeforeDrinkingStep((PickupableItem)(object)__instance); } [HarmonyPostfix] [HarmonyPatch("OnAltHeld")] private static void AfterDrinkingStep(ShipItemBottle __instance, BigContainerDrinking __state) { BigContainerDrinking.TrackIfTurnedSmall((PickupableItem)(object)__instance, __state); } [HarmonyPostfix] [HarmonyPatch("ExtraLateUpdate")] private static void AfterLateUpdate(ShipItemBottle __instance) { BigContainerDrinking.RestoreWhenDrinkingEnds((PickupableItem)(object)__instance, __instance.IsDrinking()); } } [HarmonyPatch(typeof(GoPointer), "LateUpdate")] private static class HolderPatches { private static bool Prepare() { return BigContainerDrinking.IsSupported; } [HarmonyPostfix] [HarmonyPriority(200)] private static void AfterHolderLateUpdate(GoPointer __instance) { BigContainerDrinking.EaseReturningItem(__instance); } } private const string UnsupportedWarning = "Could not find the GoPointer fields for held big items - the game may have updated. Barrels will stay small items after drinking until dropped."; } [HarmonyPatch(typeof(BilgePump), "Update")] internal static class BilgePumpPausePatch { private static bool Prepare() { bool num = AccessTools.Method(typeof(BilgePump), "Update", (Type[])null, (Type[])null) != null; if (!num) { Plugin.Log.LogWarning((object)"Could not find the bilge pump update - the game may have updated. Pausing while holding a pump handle may still knock it off its axis."); } return num; } private static bool Prefix(BilgePump __instance) { if (Time.deltaTime == 0f && ((GoPointerButton)__instance).IsStickyClicked()) { return !ModConfig.FixBilgePumpHandle.Value; } return true; } } [HarmonyPatch(typeof(GoPointer), "LateUpdate")] internal static class ButtonClickReleasePatch { private static GoPointerButton releasedClick; private static bool Prepare() { int num; if (AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null && HasField("heldItem", typeof(PickupableItem)) && HasField("clickedButton", typeof(GoPointerButton))) { num = (HasField("pointedAtButton", typeof(GoPointerButton)) ? 1 : 0); if (num != 0) { goto IL_0073; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the GoPointer click fields - the game may have updated. Climbing a ladder may still drop the held item."); goto IL_0073; IL_0073: return (byte)num != 0; } private static void Prefix(GoPointer __instance, PickupableItem ___heldItem, GoPointerButton ___clickedButton, ref GoPointerButton ___pointedAtButton) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)__instance.type == 2) { if (!GameInput.GetKey((InputName)8) && !GameInput.GetKeyUp((InputName)8)) { releasedClick = ___clickedButton; } else if (!((Object)(object)___clickedButton == (Object)null) && !((Object)(object)___clickedButton == (Object)(object)releasedClick) && !((Object)(object)___pointedAtButton != (Object)null) && !((Object)(object)___heldItem == (Object)null) && !((Object)(object)___clickedButton == (Object)(object)___heldItem) && ModConfig.FixDroppingWhileInteracting.Value) { ___pointedAtButton = ___clickedButton; } } } private static bool HasField(string name, Type type) { FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name); if (fieldInfo != null) { return fieldInfo.FieldType == type; } return false; } } [HarmonyPatch(typeof(GoPointer), "LateUpdate")] internal static class CenteredBigItemRotationPatch { private static bool Prepare() { if (!CenteredBigItemRotation.IsSupported) { Plugin.Log.LogWarning((object)"Could not find the GoPointer fields for held big items - the game may have updated. Big items will keep rotating around their pivot."); } return CenteredBigItemRotation.IsSupported; } private static void Postfix(GoPointer __instance) { CenteredBigItemRotation.KeepHeldItemCentered(__instance); } } [HarmonyPatch] internal static class CutPiecesPatches { private static bool Prepare() { int num; if (AccessTools.Method(typeof(ShipItemKnife), "OnAltActivate", (Type[])null, (Type[])null) != null) { num = ((AccessTools.Method(typeof(SaveablePrefab), "RegisterToSave", (Type[])null, (Type[])null) != null) ? 1 : 0); if (num != 0) { goto IL_004f; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the knife cut - the game may have updated. Cut pieces may still appear at one end of the item."); goto IL_004f; IL_004f: return (byte)num != 0; } [HarmonyPrefix] [HarmonyPatch(typeof(ShipItemKnife), "OnAltActivate")] [HarmonyPriority(800)] private static void BeforeCut(ShipItemKnife __instance) { CutPieces.BeforeCut(__instance); } [HarmonyFinalizer] [HarmonyPatch(typeof(ShipItemKnife), "OnAltActivate")] private static Exception AfterCut(Exception __exception) { CutPieces.AfterCut(); return __exception; } [HarmonyPostfix] [HarmonyPatch(typeof(SaveablePrefab), "RegisterToSave")] private static void AfterRegisterToSave(SaveablePrefab __instance) { CutPieces.OnRegistered(__instance); } } [HarmonyPatch(typeof(ShipItem), "DestroyItem")] internal static class DestroyedItemTwinPatch { private static bool Prepare() { int num; if (AccessTools.Method(typeof(ShipItem), "DestroyItem", (Type[])null, (Type[])null) != null) { num = ((AccessTools.Method(typeof(ShipItem), "GetItemRigidbody", (Type[])null, (Type[])null) != null) ? 1 : 0); if (num != 0) { goto IL_004f; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the item removal - the game may have updated. Cutting items on a boat may still shake it."); goto IL_004f; IL_004f: return (byte)num != 0; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null); if (list.Count > 0) { CodeInstructionExtensions.MoveLabelsFrom(val, list[0]); } list.InsertRange(0, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2] { val, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DestroyedItemTwinPatch), "DeactivateTwin", (Type[])null, (Type[])null)) }); return list; } private static void DeactivateTwin(ShipItem item) { if (ModConfig.FixBoatShakingWhenCutting.Value) { ItemRigidbody itemRigidbody = item.GetItemRigidbody(); if ((Object)(object)itemRigidbody != (Object)null) { ((Component)itemRigidbody).gameObject.SetActive(false); } } } } [HarmonyPatch(typeof(GameInput))] internal static class FocusClickInputPatches { private static bool Prepare() { int num; if (AccessTools.Method(typeof(GameInput), "GetKeyDown", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GameInput), "GetKey", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GameInput), "GetKeyUp", (Type[])null, (Type[])null) != null) { num = ((AccessTools.Method(typeof(GameInput), "GetKeyCode", (Type[])null, (Type[])null) != null) ? 1 : 0); if (num != 0) { goto IL_008b; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the game's button reads - the game may have updated. The click that focuses the game may still act in it."); goto IL_008b; IL_008b: return (byte)num != 0; } [HarmonyPrefix] [HarmonyPatch("GetKeyDown")] private static bool BeforeGetKeyDown(InputName inputName, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!FocusClick.IsSwallowing) { return true; } __result = FocusClick.GetKeyDown(inputName); return false; } [HarmonyPrefix] [HarmonyPatch("GetKey")] private static bool BeforeGetKey(InputName inputName, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!FocusClick.IsSwallowing) { return true; } __result = FocusClick.GetKey(inputName); return false; } [HarmonyPrefix] [HarmonyPatch("GetKeyUp")] private static bool BeforeGetKeyUp(InputName inputName, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!FocusClick.IsSwallowing) { return true; } __result = FocusClick.GetKeyUp(inputName); return false; } } [HarmonyPatch] internal static class FocusClickMousePatches { private static readonly Dictionary<MethodInfo, MethodInfo> Replacements = new Dictionary<MethodInfo, MethodInfo> { { MouseRead("GetMouseButtonDown"), Replacement("GetMouseButtonDown") }, { MouseRead("GetMouseButton"), Replacement("GetMouseButton") }, { MouseRead("GetMouseButtonUp"), Replacement("GetMouseButtonUp") } }; private static IEnumerable<MethodBase> TargetMethods() { return ((IEnumerable<Type>)new Type[2] { typeof(MouseButtonPointer), typeof(MapTableCamera) }).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods).Where(ReadsMouse).Cast<MethodBase>(); } private static bool Prepare(MethodBase original) { if (original != null) { return true; } bool num = TargetMethods().Any(); if (!num) { Plugin.Log.LogWarning((object)"Could not find the inventory and map mouse reads - the game may have updated. The click that focuses the game may still act in the inventory, menus or map view."); } return num; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { foreach (CodeInstruction instruction in instructions) { if (instruction.operand is MethodInfo key && Replacements.TryGetValue(key, out var value)) { instruction.operand = value; } yield return instruction; } } private static bool ReadsMouse(MethodInfo method) { if (method.GetMethodBody() == null) { return false; } return PatchProcessor.GetOriginalInstructions((MethodBase)method, (ILGenerator)null).Any((CodeInstruction code) => code.operand is MethodInfo key && Replacements.ContainsKey(key)); } private static MethodInfo MouseRead(string name) { return AccessTools.Method(typeof(Input), name, new Type[1] { typeof(int) }, (Type[])null); } private static MethodInfo Replacement(string name) { return AccessTools.Method(typeof(FocusClick), name, new Type[1] { typeof(int) }, (Type[])null); } } [HarmonyPatch] internal static class FurniturePlacingPatch { private static readonly MethodInfo Target = AccessTools.DeclaredMethod(typeof(ShipItemInkSet), "AllowOnItemClick", (Type[])null, (Type[])null); private static bool Prepare() { if (Target == null) { Plugin.Log.LogWarning((object)"Could not find the charting kit click check - the game may have updated. The charting kit may still not go on furniture."); } return Target != null; } private static MethodBase TargetMethod() { return Target; } private static void Postfix(ShipItem __instance, GoPointerButton lookedAtButton, ref bool __result) { if (!__result && !((PickupableItem)__instance).big && (Object)(object)lookedAtButton != (Object)null && lookedAtButton.allowPlacingItems && ModConfig.FixChartingKitPlacement.Value) { __result = true; } } } [HarmonyPatch(typeof(GoPointer))] internal static class FurnitureReachPatches { private static bool Prepare() { int num; if (AccessTools.Method(typeof(GoPointer), "DoRaycast", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(GoPointer), "MainButtonDown", (Type[])null, (Type[])null) != null && HasField("heldItem", typeof(PickupableItem)) && HasField("raycastRay", typeof(Ray)) && HasField("hit", typeof(RaycastHit)) && HasField("pointedAtButton", typeof(GoPointerButton))) { num = (HasField("currentLookDistance", typeof(float)) ? 1 : 0); if (num != 0) { goto IL_00e1; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the GoPointer look members - the game may have updated. Small items behind nailed furniture will stay out of reach."); goto IL_00e1; IL_00e1: return (byte)num != 0; } [HarmonyPostfix] [HarmonyPatch("DoRaycast")] [HarmonyPriority(0)] [HarmonyAfter(new string[] { "com.dizzy.sailwind.fixes", "com.dizzy.sailwind.firewoodbundle" })] private static void AfterLook(GoPointer __instance, PickupableItem ___heldItem, Ray ___raycastRay, RaycastHit ___hit, ref GoPointerButton ___pointedAtButton, ref float ___currentLookDistance) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) FurnitureReach.AfterLook(__instance, ___heldItem, ___raycastRay, ___hit, ref ___pointedAtButton, ref ___currentLookDistance); } [HarmonyPrefix] [HarmonyPatch("LateUpdate")] private static void BeforeClicks(GoPointer __instance, PickupableItem ___heldItem, ref GoPointerButton ___pointedAtButton) { FurnitureReach.BeforeClicks(__instance, ___heldItem, ref ___pointedAtButton); } private static bool HasField(string name, Type type) { FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name); if (fieldInfo != null) { return fieldInfo.FieldType == type; } return false; } } [HarmonyPatch(typeof(HangableItem))] internal static class HangingYawPatches { private sealed class HangingYaw { public readonly ShipItem Item; public Collider Hook; public Transform Boat; public int SettingVersion; public bool Upright; public float YawOnBoat; public HangingYaw(ShipItem item) { Item = item; } } private static readonly ConditionalWeakTable<HangableItem, HangingYaw> Headings = new ConditionalWeakTable<HangableItem, HangingYaw>(); private static int settingVersion; private static bool Prepare() { if (!(AccessTools.Method(typeof(HangableItem), "LateUpdate", (Type[])null, (Type[])null) != null) || !(AccessTools.Method(typeof(HangableItem), "DisconnectJoint", (Type[])null, (Type[])null) != null) || !HasField("currentHook", typeof(Collider)) || !HasField("lockX", typeof(bool)) || !HasField("lockZ", typeof(bool))) { Plugin.Log.LogWarning((object)"Could not find the hung item update - the game may have updated. Hung items may still spin on a rocking boat."); return false; } ModConfig.FixHungItemFacing.SettingChanged += delegate { settingVersion++; }; return true; } [HarmonyPostfix] [HarmonyPatch("LateUpdate")] private static void AfterLateUpdate(HangableItem __instance, Collider ___currentHook, bool ___lockX, bool ___lockZ) { //IL_00a4: 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_00ce: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (___currentHook == null || !ModConfig.FixHungItemFacing.Value || !Object.op_Implicit((Object)(object)___currentHook)) { return; } HangingYaw value = Headings.GetValue(__instance, (HangableItem hangable) => new HangingYaw(((Component)hangable).GetComponent<ShipItem>())); Transform currentActualBoat = value.Item.currentActualBoat; if (currentActualBoat == null) { value.Hook = null; return; } Transform transform = ((Component)__instance).transform; if (value.Hook != ___currentHook || value.Boat != currentActualBoat || value.SettingVersion != settingVersion) { value.Hook = ___currentHook; value.Boat = currentActualBoat; value.SettingVersion = settingVersion; value.Upright = ___lockX || ___lockZ; value.YawOnBoat = Mathf.DeltaAngle(currentActualBoat.eulerAngles.y, transform.eulerAngles.y); } else if (value.Upright) { Vector3 eulerAngles = transform.eulerAngles; eulerAngles.y = currentActualBoat.eulerAngles.y + value.YawOnBoat; transform.eulerAngles = eulerAngles; } } [HarmonyPostfix] [HarmonyPatch("DisconnectJoint")] private static void AfterDisconnectJoint(HangableItem __instance) { if (Headings.TryGetValue(__instance, out var value)) { value.Hook = null; } } private static bool HasField(string name, Type type) { FieldInfo fieldInfo = AccessTools.Field(typeof(HangableItem), name); if (fieldInfo != null) { return fieldInfo.FieldType == type; } return false; } } [HarmonyPatch] internal static class HungItemRehangPatches { private static bool Prepare() { int num; if (HungItemRehang.IsSupported && AccessTools.Method(typeof(SaveablePrefab), "Load", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(BoatLocalItems), "SpawnCachedItems", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(SaveLoadManager), "LoadGame", (Type[])null, (Type[])null) != null && AccessTools.Method(typeof(HangableItem), "FixedUpdate", (Type[])null, (Type[])null) != null) { num = ((AccessTools.Method(typeof(HangableItem), "OnTriggerEnter", (Type[])null, (Type[])null) != null) ? 1 : 0); if (num != 0) { goto IL_00b3; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the item loading or hook members - the game may have updated. Items may still fall from hooks after loading."); goto IL_00b3; IL_00b3: return (byte)num != 0; } [HarmonyPostfix] [HarmonyPatch(typeof(SaveablePrefab), "Load")] private static void AfterLoad(SaveablePrefab __instance, SavePrefabData data) { HungItemRehang.OnLoaded(__instance, data); } [HarmonyPostfix] [HarmonyPatch(typeof(BoatLocalItems), "SpawnCachedItems")] private static void AfterSpawnCachedItems() { HungItemRehang.AfterBatch(); } [HarmonyPostfix] [HarmonyPatch(typeof(SaveLoadManager), "LoadGame")] private static void AfterLoadGame() { HungItemRehang.AfterBatch(); } [HarmonyPrefix] [HarmonyPatch(typeof(HangableItem), "FixedUpdate")] private static void BeforeFixedUpdate(HangableItem __instance) { HungItemRehang.BeforeFirstPhysicsStep(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(HangableItem), "OnTriggerEnter")] private static bool BeforeTriggerEnter(HangableItem __instance) { if (__instance.IsHanging()) { return !ModConfig.FixHungItemsFalling.Value; } return true; } } [HarmonyPatch(typeof(GoPointer), "DoRaycast")] internal static class LookRayPatch { private static readonly MethodInfo VanillaRaycast = AccessTools.Method(typeof(Physics), "Raycast", new Type[4] { typeof(Ray), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int) }, (Type[])null); private static int itemInCrateMask; private static bool Prepare(MethodBase original) { if (VanillaRaycast == null) { Plugin.Log.LogWarning((object)"Could not find the look raycast - the game may have updated. Items stored in crates or behind boat walls may still be reachable."); return false; } if (original != null) { return true; } int num = LayerMask.NameToLayer("ItemInCrate"); if (num >= 0) { itemInCrateMask = 1 << num; } else { Plugin.Log.LogWarning((object)"Could not find the ItemInCrate layer - the game may have updated. Items stored in crates may still be picked up without opening them."); } if (!BoatWalls.IsSupported) { Plugin.Log.LogWarning((object)"Could not find the WalkCols layer - the game may have updated. Items behind boat walls may still be reachable."); } return true; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo operand = AccessTools.Method(typeof(LookRayPatch), "Raycast", (Type[])null, (Type[])null); List<CodeInstruction> list = new List<CodeInstruction>(instructions); bool flag = false; foreach (CodeInstruction item in list) { if (CodeInstructionExtensions.Calls(item, VanillaRaycast)) { item.operand = operand; flag = true; break; } } if (!flag) { Plugin.Log.LogError((object)"Could not find the look raycast to patch in GoPointer.DoRaycast - the game may have updated. Items stored in crates or behind boat walls may still be reachable."); } return list; } private static bool Raycast(Ray ray, out RaycastHit hit, float maxDistance, int layerMask) { //IL_0000: 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_0041: 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_0052: Unknown result type (might be due to invalid IL or missing references) bool num = Physics.Raycast(ray, ref hit, maxDistance, ReachableLayers(layerMask)); if (num && BoatWalls.IsSupported && ModConfig.FixReachingThroughWalls.Value) { ShipItem val = BoatWalls.ItemFrom(((RaycastHit)(ref hit)).collider); if ((Object)(object)val != (Object)null && BoatWalls.FindWall(((Ray)(ref ray)).origin, ((RaycastHit)(ref hit)).point, val, out var wall)) { hit = wall; } } return num; } public static int ReachableLayers(int layerMask) { if (!ModConfig.FixReachingIntoCrates.Value) { return layerMask; } return layerMask & ~itemInCrateMask; } } [HarmonyPatch(typeof(GoPointer), "DoRaycast")] internal static class WallTargetCheckPatch { private const float MaxLookDistance = 1.8f; private static bool Prepare() { int num; if (BoatWalls.IsSupported && HasField("raycastRay", typeof(Ray)) && HasField("hit", typeof(RaycastHit)) && HasField("pointedAtButton", typeof(GoPointerButton))) { num = (HasField("currentLookDistance", typeof(float)) ? 1 : 0); if (num != 0) { goto IL_0072; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the GoPointer look fields - the game may have updated. Other mods' look fixes may still reach items behind boat walls."); goto IL_0072; IL_0072: return (byte)num != 0; } [HarmonyPriority(0)] [HarmonyAfter(new string[] { "com.dizzy.sailwind.fixes", "com.dizzy.sailwind.firewoodbundle" })] private static void Postfix(Ray ___raycastRay, RaycastHit ___hit, ref GoPointerButton ___pointedAtButton, ref float ___currentLookDistance) { //IL_0043: 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_006e: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) GoPointerButton obj = ___pointedAtButton; ShipItem val = (ShipItem)(object)((obj is ShipItem) ? obj : null); if ((Object)(object)val == (Object)null || !ModConfig.FixReachingThroughWalls.Value || (Object)(object)val == (Object)(object)BoatWalls.ItemFrom(((RaycastHit)(ref ___hit)).collider)) { return; } Collider component = ((Component)val).GetComponent<Collider>(); RaycastHit val2 = default(RaycastHit); Vector3 point; if ((Object)(object)component != (Object)null && component.Raycast(___raycastRay, ref val2, 1.8f)) { point = ((RaycastHit)(ref val2)).point; } else { if (!(___currentLookDistance > 0f)) { return; } Vector3 origin = ((Ray)(ref ___raycastRay)).origin; Vector3 direction = ((Ray)(ref ___raycastRay)).direction; point = origin + ((Vector3)(ref direction)).normalized * ___currentLookDistance; } if (BoatWalls.FindWall(((Ray)(ref ___raycastRay)).origin, point, val, out var _)) { ___pointedAtButton.ForceUnlook(); ___pointedAtButton = null; ___currentLookDistance = 0f; } } private static bool HasField(string name, Type type) { FieldInfo fieldInfo = AccessTools.Field(typeof(GoPointer), name); if (fieldInfo != null) { return fieldInfo.FieldType == type; } return false; } } [HarmonyPatch(typeof(MapChartTextureRenderer), "UpdateTexture")] internal static class MapDrawingRenderPatch { private static bool Prepare() { int num; if (AccessTools.Method(typeof(MapChartTextureRenderer), "UpdateTexture", (Type[])null, (Type[])null) != null) { num = ((AccessTools.Field(typeof(MapChartTextureRenderer), "renderCam") != null) ? 1 : 0); if (num != 0) { goto IL_004d; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the map drawing renderer - the game may have updated. Map drawings may stay hidden after loading."); goto IL_004d; IL_004d: return (byte)num != 0; } private static void Postfix(MapChartTextureRenderer __instance) { if (ModConfig.FixMapDrawingsDisappearing.Value) { __instance.renderCam.Render(); } } } [HarmonyPatch(typeof(GoPointer), "LateUpdate")] internal static class MissedClickReleasePatch { private static bool Prepare() { int num; if (AccessTools.Method(typeof(GoPointer), "LateUpdate", (Type[])null, (Type[])null) != null) { num = (HasField("clickedButton", typeof(GoPointerButton)) ? 1 : 0); if (num != 0) { goto IL_0047; } } else { num = 0; } Plugin.Log.LogWarning((object)"Could not find the GoPointer click field - the game may have updated. Items clicked before a menu may stay selected after it."); goto IL_0047; IL_0047: return (byte)num != 0; } [HarmonyPriority(600)] private static void Prefix(GoPointer __instance, ref GoPointerButton ___clickedButton) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if (!((Object)(object)___clickedButton == (Object)null) && (int)__instance.type == 2 && !GameState.inCursorMenu && !BoatCamera.on && !GameInput.GetKey((