using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using BuildInSeatruckPlus.Buildables; using BuildInSeatruckPlus.Patches; using FMODUnity; using HarmonyLib; using Microsoft.CodeAnalysis; using Nautilus.Assets; using Nautilus.Assets.Gadgets; using Nautilus.Assets.PrefabTemplates; using Nautilus.Crafting; using Nautilus.Handlers; using Nautilus.Json; using Nautilus.Options.Attributes; using UWE; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("BuildInSeatruckPlus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+814d0593c0c38c63b2bb09a75cd9d28c3a1442d9")] [assembly: AssemblyProduct("BuildInSeatruckPlus")] [assembly: AssemblyTitle("BuildInSeatruckPlus")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BuildInSeatruckPlus { [Menu("Build In Seatruck Plus")] public class Config : ConfigFile { [Keybind("Playback hotkey (in Seatruck / base)")] public KeyCode Hotkey = (KeyCode)114; [Slider("Long-press seconds", 0.1f, 2f, DefaultValue = 0.5f, Step = 0.05f, Format = "{0:F2}")] public float LongPressSeconds = 0.5f; [Toggle("Cheap recipe (1 Titanium) - restart required")] public bool CheapRecipe; [Toggle("Unlock buildables at start - restart required")] public bool UnlockBuildables; [Toggle("New jukeboxes start in shuffle mode")] public bool DefaultShuffle = true; [Toggle("Show 'Now playing' notifications")] public bool ShowTrackName = true; [Choice("Don't unload containers labeled this color (needs AutosortLockers)", new string[] { })] public UnloaderSkipColor UnloaderSkipColorChoice = UnloaderSkipColor.Red; } public enum UnloaderSkipColor { Off, Red, Yellow, Green, Blue, Magenta, White } internal class HotkeyController : MonoBehaviour { private float _downTime = -1f; private bool _longFired; private void Update() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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) Config config = Plugin.Config; if (config == null || (Object)(object)Player.main == (Object)null) { return; } if (!PlayerInInterior()) { _downTime = -1f; _longFired = false; return; } if (Input.GetKeyDown(config.Hotkey)) { _downTime = Time.unscaledTime; _longFired = false; } if (_downTime >= 0f && !_longFired && Input.GetKey(config.Hotkey) && Time.unscaledTime - _downTime >= config.LongPressSeconds) { _longFired = true; TogglePlayStop(); } if (Input.GetKeyUp(config.Hotkey)) { if (_downTime >= 0f && !_longFired) { NextTrack(); } _downTime = -1f; _longFired = false; } } private static bool PlayerInInterior() { if (!(Player.main.currentInterior is SeaTruckSegment)) { return (Object)(object)Player.main.GetCurrentSub() != (Object)null; } return true; } private static JukeboxInstance ResolveInstance() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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) IInteriorSpace currentInterior = Player.main.currentInterior; ISpeakerHost host = Speaker.GetHost((MonoBehaviour)(object)((currentInterior is MonoBehaviour) ? currentInterior : null)); if (host == null && (Object)(object)Player.main.GetCurrentSub() != (Object)null) { host = Speaker.GetHost((MonoBehaviour)(object)Player.main.GetCurrentSub()); } JukeboxInstance instance = Jukebox.instance; Vector3 val = default(Vector3); float num = default(float); float num2 = default(float); if ((Object)(object)instance != (Object)null && ((Behaviour)instance).isActiveAndEnabled && Jukebox.isStartingOrPlaying && Speaker.IsSameHost(Speaker.GetHost((MonoBehaviour)(object)instance), host) && instance.GetSoundPosition(ref val, ref num, ref num2)) { return instance; } Vector3 position = ((Component)Player.main).transform.position; JukeboxInstance val2 = null; float num3 = float.MaxValue; bool flag = false; foreach (JukeboxInstance item in JukeboxInstance.all) { if (!((Object)(object)item == (Object)null) && ((Behaviour)item).isActiveAndEnabled && Speaker.IsSameHost(Speaker.GetHost((MonoBehaviour)(object)item), host)) { bool soundPosition = item.GetSoundPosition(ref val, ref num2, ref num); val = ((Component)item).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if ((Object)(object)val2 == (Object)null || (soundPosition && !flag) || (soundPosition == flag && sqrMagnitude < num3)) { val2 = item; num3 = sqrMagnitude; flag = soundPosition; } } } if (!((Object)(object)val2 != (Object)null)) { return instance; } return val2; } private void TogglePlayStop() { JukeboxInstance val = ResolveInstance(); if (!((Object)(object)val == (Object)null)) { if (Jukebox.isStartingOrPlaying && (Object)(object)Jukebox.instance == (Object)(object)val) { Jukebox.Stop(); return; } val.shuffle = Plugin.Config.DefaultShuffle; Jukebox.Play(val); } } private void NextTrack() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) JukeboxInstance val = ResolveInstance(); if ((Object)(object)val == (Object)null) { return; } string next = Jukebox.GetNext(val, true); if (string.IsNullOrEmpty(next)) { return; } val.file = next; Jukebox.Play(val); if (Plugin.Config.ShowTrackName) { string label = Jukebox.GetInfo(next).label; if (!string.IsNullOrEmpty(label)) { ErrorMessage.AddMessage("Now playing: " + label); } } } } [BepInPlugin("com.tristyn.buildinseatruckplus", "Build In Seatruck Plus", "1.0.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "com.tristyn.buildinseatruckplus"; public const string NAME = "Build In Seatruck Plus"; public const string VERSION = "1.0.8"; public static ManualLogSource Log { get; private set; } public static Config Config { get; private set; } private void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Config = OptionsPanelHandler.RegisterModOptions(); MiniBuildables.Register(); Harmony val = new Harmony("com.tristyn.buildinseatruckplus"); val.PatchAll(); ((MonoBehaviour)this).StartCoroutine(AutosortCompat.TryPatchWhenReady(val)); Log.LogInfo((object)"Build In Seatruck Plus 1.0.8 loaded."); ((Component)this).gameObject.AddComponent(); } } internal static class SeaTruckSegmentHelper { private static readonly int UseableLayer = LayerMask.NameToLayer("Useable"); public static bool isPlayerInSeaTruckSegment() { if ((Object)(object)Player.main != (Object)null) { return Player.main.currentInterior is SeaTruckSegment; } return false; } public static SeaTruckSegment getCurrentSeaTruckSegment() { if (!((Object)(object)Player.main != (Object)null)) { return null; } IInteriorSpace currentInterior = Player.main.currentInterior; return (SeaTruckSegment)(object)((currentInterior is SeaTruckSegment) ? currentInterior : null); } public static SeaTruckSegment getParentSeaTruckSegment(GameObject gameObject) { return gameObject.GetComponentInParent(); } public static SubRoot getCurrentSeaTruckSegmentSubRoot() { SeaTruckSegment currentSeaTruckSegment = getCurrentSeaTruckSegment(); if (!((Object)(object)currentSeaTruckSegment == (Object)null)) { return ((Component)currentSeaTruckSegment).gameObject.GetComponent(); } return null; } public static void NeutralizeCollidersForDocking(GameObject go) { Collider[] componentsInChildren = go.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = UseableLayer; } } public static void NeutralizeBuiltColliders(GameObject root) { if (!((Object)(object)root == (Object)null)) { Constructable[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { NeutralizeCollidersForDocking(((Component)componentsInChildren[i]).gameObject); } } } } } namespace BuildInSeatruckPlus.Patches { internal static class AutosortCompat { private const string UnloaderTypeName = "AutosortLockers.AutosortUnloader"; private const string MethodName = "AccumulateUnloadTargets"; private static bool done; internal static IEnumerator TryPatchWhenReady(Harmony harmony) { for (int attempt = 0; attempt < 10; attempt++) { if (done) { break; } if (TryPatch(harmony)) { break; } yield return (object)new WaitForSeconds(1f); } } private static bool TryPatch(Harmony harmony) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (done) { return true; } try { Type type = AccessTools.TypeByName("AutosortLockers.AutosortUnloader"); if (type == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type, "AccumulateUnloadTargets", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogInfo((object)"AutosortLockers present but AccumulateUnloadTargets not found; planter-protection patch skipped."); done = true; return true; } HarmonyMethod val = new HarmonyMethod(typeof(AutosortCompat), "AccumulateUnloadTargets_Postfix", (Type[])null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); done = true; Plugin.Log.LogInfo((object)"AutosortLockers detected — unloader patched to leave Seatruck planters alone."); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("AutosortLockers planter-protection patch failed (harmless): " + ex.Message)); done = true; return true; } } private static void AccumulateUnloadTargets_Postfix(object __instance) { try { List value = Traverse.Create(__instance).Field("containerTargets").GetValue>(); if (value == null || value.Count == 0) { return; } Planter[] planters = Object.FindObjectsOfType(); if (planters.Length != 0) { value.RemoveAll((ItemsContainer ct) => ct != null && planters.Any((Planter p) => (Object)(object)p != (Object)null && (Object)(object)p.storageContainer != (Object)null && p.storageContainer.container == ct)); } RemoveColorMarkedContainers(value); } catch (Exception ex) { Plugin.Log.LogWarning((object)("AutosortLockers protection postfix error (harmless): " + ex.Message)); } } private static void RemoveColorMarkedContainers(List list) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (list == null || list.Count == 0) { return; } UnloaderSkipColor unloaderSkipColor = ((Plugin.Config != null) ? Plugin.Config.UnloaderSkipColorChoice : UnloaderSkipColor.Off); if (unloaderSkipColor == UnloaderSkipColor.Off) { return; } ColoredLabel[] array = Object.FindObjectsOfType(); if (array.Length == 0) { return; } HashSet protectedContainers = new HashSet(); ColoredLabel[] array2 = array; foreach (ColoredLabel val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)val.signInput == (Object)null) { continue; } Color[] colors = val.signInput.colors; int colorIndex = val.signInput.colorIndex; if (colors != null && colorIndex >= 0 && colorIndex < colors.Length && Classify(colors[colorIndex]) == unloaderSkipColor) { StorageContainer val2 = ResolveContainer(val); if ((Object)(object)val2 != (Object)null && val2.container != null) { protectedContainers.Add(val2.container); } } } if (protectedContainers.Count > 0) { list.RemoveAll((ItemsContainer ct) => ct != null && protectedContainers.Contains(ct)); } } private static StorageContainer ResolveContainer(ColoredLabel cl) { //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_0030: Unknown result type (might be due to invalid IL or missing references) StorageContainer componentInParent = GetComponentExtensions.GetComponentInParent((Component)(object)cl, true); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } Vector3 position = ((Component)cl).transform.position; Transform parent = ((Component)cl).transform.parent; int num = 0; while (num < 4 && (Object)(object)parent != (Object)null) { StorageContainer val = NearestContainer(parent, position); if ((Object)(object)val != (Object)null) { return val; } num++; parent = parent.parent; } return null; } private static StorageContainer NearestContainer(Transform scope, Vector3 lp) { //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_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) StorageContainer result = null; float num = float.MaxValue; StorageContainer[] componentsInChildren = ((Component)scope).GetComponentsInChildren(true); foreach (StorageContainer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.container != null) { Vector3 val2 = ((Component)val).transform.position - lp; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val; } } } return result; } private static UnloaderSkipColor Classify(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); if (num3 < 0.15f) { return UnloaderSkipColor.Off; } if (num2 < 0.25f) { return UnloaderSkipColor.White; } float num4 = num * 360f; if (num4 < 20f || num4 >= 330f) { return UnloaderSkipColor.Red; } if (num4 < 70f) { return UnloaderSkipColor.Yellow; } if (num4 < 170f) { return UnloaderSkipColor.Green; } if (num4 < 260f) { return UnloaderSkipColor.Blue; } return UnloaderSkipColor.Magenta; } } [HarmonyPatch(typeof(Builder), "CheckAsSubModule")] internal static class Builder_CheckAsSubModule_Patch { private static bool Prefix(out Collider hitCollider, ref bool __result) { //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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) hitCollider = null; if ((Object)(object)SeaTruckSegmentHelper.getCurrentSeaTruckSegment() == (Object)null) { return true; } Builder.placementTarget = null; Transform aimTransform = Builder.GetAimTransform(); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(aimTransform.position, aimTransform.forward, ref val, Builder.placeMaxDistance, ((LayerMask)(ref Builder.placeLayerMask)).value, (QueryTriggerInteraction)1)) { __result = false; return false; } if (!Constructable.CheckFlags(Builder.allowedInBase, Builder.allowedInSub, Builder.allowedOutside, Builder.allowedUnderwater, ((RaycastHit)(ref val)).point)) { __result = false; return false; } hitCollider = ((RaycastHit)(ref val)).collider; Builder.placementTarget = ((Component)hitCollider).gameObject; Builder.SetPlaceOnSurface(val, ref Builder.placePosition, ref Builder.placeRotation); __result = true; return false; } } [HarmonyPatch(typeof(Builder), "TryPlace")] internal static class Builder_TryPlace_Patch { private static bool Prefix(ref bool __result) { //IL_002c: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) SeaTruckSegment currentSeaTruckSegment = SeaTruckSegmentHelper.getCurrentSeaTruckSegment(); if ((Object)(object)currentSeaTruckSegment == (Object)null) { return true; } if ((Object)(object)Builder.prefab == (Object)null || !Builder.canPlace) { RuntimeManager.PlayOneShot("event:/bz/ui/item_error", default(Vector3)); __result = false; return false; } RuntimeManager.PlayOneShot("event:/tools/builder/place", Builder.ghostModel.transform.position); GameObject obj = Object.Instantiate(Builder.prefab); SeaTruckSegment val = (((Object)(object)Builder.placementTarget != (Object)null) ? SeaTruckSegmentHelper.getParentSeaTruckSegment(Builder.placementTarget) : null); SeaTruckSegment val2 = (((Object)(object)val != (Object)null) ? val : currentSeaTruckSegment); obj.transform.parent = ((Component)val2).transform; obj.transform.position = Builder.placePosition; obj.transform.rotation = Builder.placeRotation; Constructable componentInParent = obj.GetComponentInParent(); componentInParent.SetState(false, true); if ((Object)(object)Builder.ghostModel != (Object)null) { Object.Destroy((Object)(object)Builder.ghostModel); } componentInParent.SetIsInside(true); SkyEnvironmentChanged.Send(obj, (Component)(object)val2); SeaTruckSegmentHelper.NeutralizeCollidersForDocking(obj); Builder.ghostModel = null; Builder.prefab = null; Builder.canPlace = false; __result = true; return false; } } [HarmonyPatch(typeof(Builder), "CheckTag")] internal static class Builder_CheckTag_Patch { private static bool Prefix(Collider c, ref bool __result) { if ((Object)(object)c != (Object)null && (Object)(object)((Component)c).GetComponentInParent() != (Object)null) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(CanvasLink), "SetCanvasesEnabled")] internal static class CanvasLink_SetCanvasesEnabled_Patch { private static readonly FieldInfo Field = AccessTools.Field(typeof(CanvasLink), "canvases"); private static bool Prefix(CanvasLink __instance, bool enabled) { return CanvasLinkToggle.Run(Field, __instance, enabled); } } [HarmonyPatch(typeof(CanvasLink), "SetRectMasksEnabled")] internal static class CanvasLink_SetRectMasksEnabled_Patch { private static readonly FieldInfo Field = AccessTools.Field(typeof(CanvasLink), "rectMasks"); private static bool Prefix(CanvasLink __instance, bool enabled) { return CanvasLinkToggle.Run(Field, __instance, enabled); } } internal static class CanvasLinkToggle { public static bool Run(FieldInfo field, CanvasLink instance, bool enabled) { if (field.GetValue(instance) is Behaviour[] array) { Behaviour[] array2 = array; foreach (Behaviour val in array2) { if ((Object)(object)val != (Object)null) { val.enabled = enabled; } } } return false; } } [HarmonyPatch(typeof(Constructable), "CheckFlags")] internal static class Constructable_CheckFlags_Patch { private static bool Prefix(ref bool __result) { if ((Object)(object)SeaTruckSegmentHelper.getCurrentSeaTruckSegment() == (Object)null) { return true; } __result = true; return false; } } internal static class DockedAudio { internal static readonly List Moonpools = new List(); } [HarmonyPatch(typeof(MoonpoolExpansionManager), "Start")] internal static class MoonpoolExpansionManager_Start_Patch { private static void Postfix(MoonpoolExpansionManager __instance) { if (!DockedAudio.Moonpools.Contains(__instance)) { DockedAudio.Moonpools.Add(__instance); } } } [HarmonyPatch(typeof(Speaker), "GetSpeakers")] internal static class Speaker_GetSpeakers_Patch { private static bool _bridging; private static readonly List _other = new List(); private static void Postfix(ISpeakerHost host, Vector3 position, float radius, List results) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if (_bridging || host == null) { return; } _bridging = true; try { for (int num = DockedAudio.Moonpools.Count - 1; num >= 0; num--) { MoonpoolExpansionManager val = DockedAudio.Moonpools[num]; if ((Object)(object)val == (Object)null) { DockedAudio.Moonpools.RemoveAt(num); continue; } SeaTruckSegment dockedHead = val.GetDockedHead(); SeaTruckSegment dockedTail = val.GetDockedTail(); if ((Object)(object)dockedHead == (Object)null && (Object)(object)dockedTail == (Object)null) { continue; } BaseRoot baseRoot = val.baseRoot; int num2; if (host is BaseRoot) { num2 = (((object)host == baseRoot) ? 1 : 0); if (num2 != 0) { goto IL_00b5; } } else { num2 = 0; } if (!(host is SeaTruckSegment)) { goto IL_00b5; } int num3 = ((((Object)(object)dockedTail != (Object)null && Speaker.IsSameHost(host, (ISpeakerHost)(object)dockedTail)) || ((Object)(object)dockedHead != (Object)null && Speaker.IsSameHost(host, (ISpeakerHost)(object)dockedHead))) ? 1 : 0); goto IL_00b6; IL_00b6: bool flag = (byte)num3 != 0; if (num2 != 0) { Append((ISpeakerHost)(object)dockedTail, position, radius, results); Append((ISpeakerHost)(object)dockedHead, position, radius, results); } else if (flag) { Append((ISpeakerHost)(object)baseRoot, position, radius, results); } continue; IL_00b5: num3 = 0; goto IL_00b6; } } finally { _bridging = false; } } private static void Append(ISpeakerHost other, Vector3 position, float radius, List results) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (other == null) { return; } _other.Clear(); Speaker.GetSpeakers(other, position, radius, _other); for (int i = 0; i < _other.Count; i++) { Speaker val = _other[i]; if ((Object)(object)val != (Object)null && !results.Contains(val)) { results.Add(val); } } } } [HarmonyPatch(typeof(Speaker), "IsSameHost")] internal static class Speaker_IsSameHost_Patch { private static bool _reentry; private static void Postfix(ISpeakerHost a, ISpeakerHost b, ref bool __result) { if (__result || _reentry || a == null || b == null) { return; } _reentry = true; try { for (int num = DockedAudio.Moonpools.Count - 1; num >= 0; num--) { MoonpoolExpansionManager val = DockedAudio.Moonpools[num]; if ((Object)(object)val == (Object)null) { DockedAudio.Moonpools.RemoveAt(num); } else { SeaTruckSegment dockedHead = val.GetDockedHead(); SeaTruckSegment dockedTail = val.GetDockedTail(); if ((!((Object)(object)dockedHead == (Object)null) || !((Object)(object)dockedTail == (Object)null)) && InGroup(a, val, dockedHead, dockedTail) && InGroup(b, val, dockedHead, dockedTail)) { __result = true; break; } } } } finally { _reentry = false; } } private static bool InGroup(ISpeakerHost h, MoonpoolExpansionManager mp, SeaTruckSegment head, SeaTruckSegment tail) { if (h is BaseRoot && (object)h == mp.baseRoot) { return true; } if ((Object)(object)head != (Object)null && Speaker.IsSameHost(h, (ISpeakerHost)(object)head)) { return true; } if ((Object)(object)tail != (Object)null && Speaker.IsSameHost(h, (ISpeakerHost)(object)tail)) { return true; } return false; } } [HarmonyPatch(typeof(SeaTruckMotor), "StartPiloting")] internal static class SeaTruckMotor_StartPiloting_Patch { private static void Postfix(SeaTruckMotor __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.truckSegment != (Object)null) { SeaTruckSegmentHelper.NeutralizeBuiltColliders(((Component)__instance.truckSegment).gameObject); } } } [HarmonyPatch(typeof(MoonpoolExpansionManager), "StartUndocking")] internal static class MoonpoolExpansionManager_StartUndocking_Patch { private static void Postfix(MoonpoolExpansionManager __instance) { SeaTruckSegment dockedHead = __instance.GetDockedHead(); if ((Object)(object)dockedHead != (Object)null) { SeaTruckSegmentHelper.NeutralizeBuiltColliders(((Component)dockedHead).gameObject); } SeaTruckSegment dockedTail = __instance.GetDockedTail(); if ((Object)(object)dockedTail != (Object)null) { SeaTruckSegmentHelper.NeutralizeBuiltColliders(((Component)dockedTail).gameObject); } } } [HarmonyPatch(typeof(JukeboxInstance), "ConsumePower")] internal static class JukeboxInstance_ConsumePower_Patch { private static void Prefix(JukeboxInstance __instance) { if (!((Object)(object)__instance._powerRelay != (Object)null)) { PowerRelay componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { __instance._powerRelay = componentInParent; Plugin.Log.LogInfo((object)("Re-resolved missing PowerRelay for " + ((Object)__instance).name + " -> " + ((Object)componentInParent).name + " (load-timing fix).")); } } } } internal static class JukeboxSync { internal static bool InDisable; private static int _frame = -1; private static readonly Dictionary _cache = new Dictionary(); internal static bool IsMirror(JukeboxInstance ji) { if (Time.frameCount != _frame) { _frame = Time.frameCount; _cache.Clear(); } if (_cache.TryGetValue(ji, out var value)) { return value; } bool flag = Compute(ji); _cache[ji] = flag; return flag; } private static bool Compute(JukeboxInstance ji) { JukeboxInstance instance = Jukebox.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)ji) { return false; } if (!Jukebox.isStartingOrPlaying) { return false; } return Speaker.IsSameHost(Speaker.GetHost((MonoBehaviour)(object)ji), Speaker.GetHost((MonoBehaviour)(object)instance)); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class JukeboxInstance_isControlling_Patch { private static void Postfix(JukeboxInstance __instance, ref bool __result) { if (!__result && !JukeboxSync.InDisable && JukeboxSync.IsMirror(__instance)) { __result = true; } } } [HarmonyPatch(typeof(JukeboxInstance), "UpdatePower")] internal static class JukeboxInstance_UpdatePower_Patch { private static bool Prefix(JukeboxInstance __instance) { return !JukeboxSync.IsMirror(__instance); } } [HarmonyPatch(typeof(JukeboxInstance), "OnDisable")] internal static class JukeboxInstance_OnDisable_Patch { private static void Prefix() { JukeboxSync.InDisable = true; } private static void Finalizer() { JukeboxSync.InDisable = false; } } [HarmonyPatch(typeof(JukeboxInstance), "UpdateUI")] internal static class JukeboxInstance_UpdateUI_Patch { private static void Prefix(JukeboxInstance __instance) { //IL_0039: 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_0048: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (!JukeboxSync.IsMirror(__instance)) { return; } JukeboxInstance instance = Jukebox.instance; if (!((Object)(object)instance == (Object)null)) { if (__instance.file != instance.file) { __instance.file = instance.file; } if (__instance.repeat != instance.repeat) { __instance.repeat = instance.repeat; __instance.imageRepeat.sprite = __instance.spritesRepeat[instance.repeat]; } if (__instance.shuffle != instance.shuffle) { __instance.shuffle = instance.shuffle; __instance.imageShuffle.sprite = (instance.shuffle ? __instance.spriteShuffleOn : __instance.spriteShuffleOff); } } } } internal static class PlanterDiagnostics { private const string Tag = "[PlantDiag]"; internal static bool IsSeatruckPlanter(Planter p) { if ((Object)(object)p != (Object)null) { return (Object)(object)((Component)p).GetComponentInParent() != (Object)null; } return false; } internal static string PlanterId(Planter p) { UniqueIdentifier val = ((Component)p).GetComponent() ?? ((Component)p).GetComponentInParent(); if (!((Object)(object)val != (Object)null)) { return ""; } return val.Id; } internal static void Dump(Planter p, string phase) { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)p == (Object)null) { return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[PlantDiag]").Append(' ').Append(phase) .Append(" planter=") .Append(PlanterId(p)); SeaTruckSegment componentInParent = ((Component)p).GetComponentInParent(); stringBuilder.Append(" seg=").Append(((Object)(object)componentInParent != (Object)null) ? ((Object)componentInParent).name : ""); int value = (((Object)(object)p.grownPlantsRoot != (Object)null) ? p.grownPlantsRoot.childCount : (-1)); stringBuilder.Append(" grownModels=").Append(value); Transform val = (((Object)(object)p.storageContainer != (Object)null && (Object)(object)p.storageContainer.storageRoot != (Object)null) ? ((Component)p.storageContainer.storageRoot).transform : null); int value2 = (((Object)(object)val != (Object)null) ? val.childCount : (-1)); stringBuilder.Append(" storedItems=").Append(value2); Plugin.Log.LogInfo((object)stringBuilder.ToString()); if (!((Object)(object)val != (Object)null)) { return; } for (int i = 0; i < val.childCount; i++) { Transform child = val.GetChild(i); StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.Append("[PlantDiag]").Append(" item[").Append(i) .Append("] ") .Append(((Object)child).name); Pickupable component = ((Component)child).GetComponent(); stringBuilder2.Append(" tech=").Append(((Object)(object)component != (Object)null) ? ((object)component.GetTechType()/*cast due to .constrained prefix*/).ToString() : ""); Plantable component2 = ((Component)child).GetComponent(); if ((Object)(object)component2 != (Object)null) { stringBuilder2.Append(" slot=").Append(component2.planterSlotId).Append(" age=") .Append(component2.plantAge.ToString("0.000")); } UniqueIdentifier component3 = ((Component)child).GetComponent(); stringBuilder2.Append(" uid=").Append(((Object)(object)component3 != (Object)null) ? component3.Id : "").Append(" active=") .Append(((Component)child).gameObject.activeSelf); Plugin.Log.LogInfo((object)stringBuilder2.ToString()); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[PlantDiag] dump failed: " + ex.Message)); } } internal static IEnumerator DumpDelayed(Planter p, string phase, float seconds) { yield return (object)new WaitForSeconds(seconds); Dump(p, phase); } } [HarmonyPatch(typeof(Planter), "OnProtoSerializeObjectTree")] internal static class Planter_OnProtoSerializeObjectTree_Diag { private static void Postfix(Planter __instance) { if (PlanterDiagnostics.IsSeatruckPlanter(__instance)) { PlanterDiagnostics.Dump(__instance, "SAVE"); } } } [HarmonyPatch(typeof(Planter), "OnProtoDeserializeObjectTree")] internal static class Planter_OnProtoDeserializeObjectTree_Diag { private static void Postfix(Planter __instance) { if (PlanterDiagnostics.IsSeatruckPlanter(__instance)) { PlanterDiagnostics.Dump(__instance, "LOAD-start"); CoroutineHost.StartCoroutine(PlanterDiagnostics.DumpDelayed(__instance, "LOAD+5s", 5f)); } } } [HarmonyPatch(typeof(Planter), "ReplaceItem")] internal static class Planter_ReplaceItem_Diag { private static void Postfix(Planter __instance, Plantable seed, Plantable plant, bool __result) { //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_0066: 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) if (!PlanterDiagnostics.IsSeatruckPlanter(__instance)) { return; } try { string arg = (((Object)(object)seed != (Object)null && (Object)(object)seed.pickupable != (Object)null) ? ((object)seed.pickupable.GetTechType()/*cast due to .constrained prefix*/).ToString() : ""); string arg2 = (((Object)(object)plant != (Object)null && (Object)(object)plant.pickupable != (Object)null) ? ((object)plant.pickupable.GetTechType()/*cast due to .constrained prefix*/).ToString() : ""); Plugin.Log.LogInfo((object)("[PlantDiag] REPLACE (seed->plant) planter=" + PlanterDiagnostics.PlanterId(__instance) + " " + $"seed={arg} plant={arg2} result={__result}")); } catch { } } } [HarmonyPatch(typeof(Planter), "SetupRenderers")] internal static class Planter_SetupRenderers_Patch { private static void Postfix(Planter __instance, GameObject gameObject) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)gameObject == (Object)null) && !((Object)(object)((Component)__instance).GetComponentInParent() == (Object)null)) { SeaTruckSegmentHelper.NeutralizeCollidersForDocking(gameObject); } } } [HarmonyPatch(typeof(PowerConsumer), "IsPowered")] internal static class PowerConsumer_IsPowered_Patch { private static bool Prefix(PowerConsumer __instance, ref bool __result) { SeaTruckSegment parentSeaTruckSegment = SeaTruckSegmentHelper.getParentSeaTruckSegment(((Component)__instance).gameObject); if ((Object)(object)parentSeaTruckSegment == (Object)null) { return true; } __result = ((IInteriorSpace)parentSeaTruckSegment).CanBreathe(); return false; } } [HarmonyPatch(typeof(SeaTruckSegment), "CanEnter")] internal static class SeaTruckSegment_CanEnter_Patch { private static bool Prefix(ref bool __result) { __result = true; return false; } } } namespace BuildInSeatruckPlus.Buildables { internal static class MiniBuildables { public static TechType MiniJukebox { get; private set; } public static TechType MiniSpeaker { get; private set; } public static void Register() { //IL_0019: 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) MiniJukebox = Make("MiniJukebox", "Mini Jukebox", "A compact jukebox that fits inside a Seatruck.", (TechType)1564, 0.25f); MiniSpeaker = Make("MiniSpeaker", "Mini Speaker", "A compact speaker for tight interiors.", (TechType)1566, 0.5f); } private static TechType Make(string classId, string friendly, string description, TechType cloneOf, float scale) { //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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0040: 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_0048: Expected O, but got Unknown //IL_0097: 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_008e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00b2: 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_00d1: 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_00fc: Unknown result type (might be due to invalid IL or missing references) PrefabInfo val = PrefabInfo.WithTechType(classId, friendly, description, "English", false, (Assembly)null); PrefabInfo val2 = ((PrefabInfo)(ref val)).WithIcon(SpriteManager.Get(cloneOf)); CustomPrefab val3 = new CustomPrefab(val2); CloneTemplate val4 = new CloneTemplate(val2, cloneOf); val4.ModifyPrefab = (Action)Delegate.Combine(val4.ModifyPrefab, (Action)delegate(GameObject go) { //IL_0007: 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_0030: 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) Transform transform = go.transform; transform.localScale *= scale; ConstructableBounds[] componentsInChildren = go.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].bounds.extents = Vector3.one * 0.02f; } Plugin.Log.LogInfo((object)$"{classId}: scaled to {scale} with liberal bounds."); }); val3.SetGameObject((PrefabTemplate)(object)val4); RecipeData val5 = (RecipeData)((!Plugin.Config.CheapRecipe) ? (((object)CraftDataHandler.GetRecipeData(cloneOf)) ?? ((object)new RecipeData((Ingredient[])(object)new Ingredient[1] { new Ingredient((TechType)16, 1) }))) : ((object)new RecipeData((Ingredient[])(object)new Ingredient[1] { new Ingredient((TechType)16, 1) }))); GadgetExtensions.SetRecipe((ICustomPrefab)(object)val3, val5); TechGroup val6 = default(TechGroup); TechCategory val7 = default(TechCategory); int num = default(int); if (CraftData.GetBuilderIndex(cloneOf, ref val6, ref val7, ref num)) { GadgetExtensions.SetPdaGroupCategory((ICustomPrefab)(object)val3, val6, val7); } if (!Plugin.Config.UnlockBuildables) { GadgetExtensions.SetUnlock((ICustomPrefab)(object)val3, (TechType)1564, 1); } val3.Register(); return ((PrefabInfo)(ref val2)).TechType; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }