Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LetsBuild v0.6.4
plugins/LetsBuild.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DezzyCode")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("DezzyCode")] [assembly: AssemblyDescription("A creative builder's hammer, precision building, and grid planting.")] [assembly: AssemblyFileVersion("0.6.4.0")] [assembly: AssemblyInformationalVersion("0.6.4+b7227102362cc88e48c647f158b8ae3fbdbc8943")] [assembly: AssemblyProduct("Lets Build")] [assembly: AssemblyTitle("LetsBuild")] [assembly: AssemblyVersion("0.6.4.0")] [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 LetsBuild { [HarmonyPatch] internal static class BuildCamera { private const float Speed = 10f; private const float MaxPitch = 89f; private static readonly MethodInfo PlayerTakesInput = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude"); private static bool _loose; private static Vector3 _position; private static float _yaw; private static float _pitch; private static Vector3 _start; private static readonly List<Renderer> Hidden = new List<Renderer>(); private static readonly List<Collider> Disabled = new List<Collider>(); private static bool _flightReading; public static void Tick(Player player) { if (_loose && ((Object)(object)player == (Object)null || ((Character)player).IsDead() || !CreativeMode.Active)) { Fix(player); } else { if ((Object)(object)player == (Object)null || !CreativeMode.Active) { return; } if (Keys.Down(Settings.CameraKey) && Listening(player)) { if (_loose) { Fix(player); } else { Loosen(player); } } if (_loose && Listening(player) && !Hud.IsPieceSelectionVisible() && !Hud.InRadial()) { Fly(Time.unscaledDeltaTime); } } } private static bool Listening(Player player) { if (!(PlayerTakesInput == null)) { return (bool)PlayerTakesInput.Invoke(player, null); } return true; } private static void Loosen(Player player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0036: 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_003f: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform : null); if (!((Object)(object)val == (Object)null)) { _position = val.position; Quaternion rotation = val.rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; _yaw = eulerAngles.y; _pitch = Mathf.Clamp(Mathf.DeltaAngle(0f, eulerAngles.x), -89f, 89f); _start = ((Component)player).transform.position; Hide(player); _loose = true; ((Character)player).Message((MessageType)1, "$lb_camera_loose", 0, (Sprite)null, false); } } private static void Fix(Player player) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) _loose = false; if ((Object)(object)player == (Object)null) { Hidden.Clear(); Disabled.Clear(); return; } Show(); if (!player.InDebugFlyMode()) { Teleport(player, _start); MaxAirAltitude.Invoke((Character)(object)player) = _start.y; } ((Character)player).Message((MessageType)1, "$lb_camera_fixed", 0, (Sprite)null, false); } private static void Fly(float dt) { //IL_0000: 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) //IL_000f: 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_003b: 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_006a: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_007f: 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) //IL_0089: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00a7: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00e8: 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_00f6: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: 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) Vector2 val = ZInput.GetMouseDelta() * PlayerController.m_mouseSens; if (PlayerController.m_invertMouse) { val.y = 0f - val.y; } _yaw += val.x; _pitch = Mathf.Clamp(_pitch - val.y, -89f, 89f); Quaternion val2 = Quaternion.Euler(_pitch, _yaw, 0f); Vector3 val3 = Vector3.zero; if (ZInput.GetButton("Forward")) { val3 += val2 * Vector3.forward; } if (ZInput.GetButton("Backward")) { val3 += val2 * Vector3.back; } if (ZInput.GetButton("Left")) { val3 += val2 * Vector3.left; } if (ZInput.GetButton("Right")) { val3 += val2 * Vector3.right; } if (ZInput.GetButton("Jump")) { val3 += Vector3.up; } if (ZInput.GetButton("Crouch")) { val3 += Vector3.down; } if (((Vector3)(ref val3)).sqrMagnitude > 1f) { ((Vector3)(ref val3)).Normalize(); } _position += val3 * (10f * dt); } private static void Hide(Player player) { Hidden.Clear(); Renderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (val.enabled) { val.enabled = false; Hidden.Add(val); } } Disabled.Clear(); Collider[] componentsInChildren2 = ((Component)player).GetComponentsInChildren<Collider>(); foreach (Collider val2 in componentsInChildren2) { if (val2.enabled && !val2.isTrigger) { val2.enabled = false; Disabled.Add(val2); } } } private static void Show() { foreach (Renderer item in Hidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } foreach (Collider item2 in Disabled) { if ((Object)(object)item2 != (Object)null) { item2.enabled = true; } } Hidden.Clear(); Disabled.Clear(); } private static void Carry(Player player) { //IL_0015: 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_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_002c: 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_0032: 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) if (!((Object)(object)((Character)player).m_eye == (Object)null)) { Vector3 val = ((Character)player).m_eye.position - ((Component)player).transform.position; Teleport(player, _position - val); MaxAirAltitude.Invoke((Character)(object)player) = ((Component)player).transform.position.y; } } private static void Teleport(Player player, Vector3 position) { //IL_0006: 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_0024: Unknown result type (might be due to invalid IL or missing references) ((Component)player).transform.position = position; Rigidbody component = ((Component)player).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.position = position; component.linearVelocity = Vector3.zero; component.useGravity = false; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPostfix] private static void Place(GameCamera __instance) { //IL_000e: 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) if (_loose) { ((Component)__instance).transform.position = _position; ((Component)__instance).transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Carry(localPlayer); } } } [HarmonyPatch(typeof(Character), "UpdateDebugFly")] [HarmonyPrefix] private static void FlightReads(Character __instance) { _flightReading = _loose && (Object)(object)__instance == (Object)(object)Player.m_localPlayer; } [HarmonyPatch(typeof(Character), "UpdateDebugFly")] [HarmonyFinalizer] private static void FlightDone() { _flightReading = false; } [HarmonyPatch(typeof(Player), "TakeInput")] [HarmonyPrefix] private static bool FlightInput(ref bool __result) { if (!_flightReading) { return true; } __result = false; return false; } [HarmonyPatch(typeof(PlayerController), "TakeInput")] [HarmonyPrefix] private static bool CharacterInput(ref bool __result) { if (!_loose) { return true; } __result = false; return false; } } internal static class CreativeHammer { public const string PrefabName = "LetsBuild_Hammer"; public const string NameToken = "$lb_hammer"; private const string IconFile = "hammer.png"; public static void Register() { PrefabManager.OnVanillaPrefabsAvailable += Create; } public static bool IsHammer(ItemData item) { if (item?.m_shared != null) { return item.m_shared.m_name == "$lb_hammer"; } return false; } private static void Create() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0074: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Create; ItemConfig val = new ItemConfig(); val.Name = "$lb_hammer"; val.Description = "$lb_hammer_desc"; val.CraftingStation = CraftingStations.Workbench; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Wood", Amount = 1, Recover = true } }; ItemConfig val2 = val; CustomItem val3 = (Settings.Craftable.Value ? new CustomItem("LetsBuild_Hammer", "Hammer", val2) : new CustomItem("LetsBuild_Hammer", "Hammer")); if ((Object)(object)val3.ItemPrefab == (Object)null) { Log.Warning("Could not clone the vanilla hammer; the builder's hammer is unavailable."); return; } SharedData shared = val3.ItemDrop.m_itemData.m_shared; shared.m_name = "$lb_hammer"; shared.m_description = "$lb_hammer_desc"; shared.m_useDurability = false; Sprite val4 = LoadIcon(); if ((Object)(object)val4 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 }; } ItemManager.Instance.AddItem(val3); Log.Info(Settings.Craftable.Value ? "Builder's hammer registered, craftable at the workbench." : "Builder's hammer registered; spawn it with \"spawn LetsBuild_Hammer\"."); } private static Sprite LoadIcon() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00d0: 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) string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = ((directoryName != null) ? Path.Combine(directoryName, "hammer.png") : null); if (text == null || !File.Exists(text)) { Log.Warning("hammer.png is not next to the DLL; the hammer keeps the vanilla icon."); return null; } MethodInfo methodInfo = AccessTools.Method("UnityEngine.ImageConversion:LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }, (Type[])null); if (methodInfo == null) { Log.Warning("Cannot decode hammer.png; the hammer keeps the vanilla icon."); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!(bool)methodInfo.Invoke(null, new object[2] { val, File.ReadAllBytes(text) })) { Object.Destroy((Object)(object)val); Log.Warning("hammer.png could not be decoded; the hammer keeps the vanilla icon."); return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } [HarmonyPatch] internal static class CreativeMode { private static bool _active; private static bool _hadCheats; private static bool _hadDebug; private static bool _hadFly; private static bool _hadFreeBuild; private static bool _flyOffPending; private static bool _silent; public static bool Active => _active; [HarmonyPatch(typeof(Humanoid), "EquipItem")] [HarmonyPostfix] private static void Equipped(Humanoid __instance, ItemData item, bool __result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (__result && IsOurs(__instance, item)) { Enter((Player)__instance); } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] [HarmonyPostfix] private static void Unequipped(Humanoid __instance, ItemData item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown if (IsOurs(__instance, item)) { Leave((Player)__instance); } } [HarmonyPatch(typeof(Player), "OnDestroy")] [HarmonyPrefix] private static void PlayerGone(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && _active) { _active = false; _flyOffPending = false; Terminal.m_cheat = _hadCheats; Player.m_debugMode = _hadDebug; Log.Info("Creative mode off; the world closed while the hammer was held."); } } [HarmonyPatch(typeof(Player), "Message")] [HarmonyPrefix] private static bool Quiet() { return !_silent; } private static bool IsOurs(Humanoid humanoid, ItemData item) { if ((Object)(object)humanoid == (Object)(object)Player.m_localPlayer) { return CreativeHammer.IsHammer(item); } return false; } private static void Enter(Player player) { if (_active) { return; } if (Settings.AdminOnly.Value && !IsAdmin()) { ((Character)player).Message((MessageType)2, "$lb_admin_only", 0, (Sprite)null, false); return; } _hadCheats = Terminal.m_cheat; _hadDebug = Player.m_debugMode; _hadFly = player.InDebugFlyMode(); _hadFreeBuild = player.NoCostCheat(); _flyOffPending = false; _active = true; Terminal.m_cheat = true; Player.m_debugMode = true; Silently(delegate { player.SetNoPlacementCost(true); if (!_hadFly && Settings.Fly.Value) { player.ToggleDebugFly(); } }); ((Character)player).Message((MessageType)1, "$lb_creative_on", 0, (Sprite)null, false); Log.Info("Creative mode on (was: cheats " + _hadCheats + ", debug " + _hadDebug + ", fly " + _hadFly + ", free build " + _hadFreeBuild + ")."); } private static void Leave(Player player) { if (!_active) { return; } _active = false; Terminal.m_cheat = _hadCheats; Player.m_debugMode = _hadDebug; Silently(delegate { player.SetNoPlacementCost(_hadFreeBuild); }); if (player.InDebugFlyMode() == _hadFly) { ((Character)player).Message((MessageType)1, "$lb_creative_off", 0, (Sprite)null, false); Log.Info("Creative mode off."); } else if (((Character)player).IsOnGround()) { Silently(delegate { player.ToggleDebugFly(); }); ((Character)player).Message((MessageType)1, "$lb_creative_off", 0, (Sprite)null, false); Log.Info("Creative mode off."); } else { _flyOffPending = true; ((Character)player).Message((MessageType)1, "$lb_fly_until_landed", 0, (Sprite)null, false); Log.Info("Creative mode off; flight stays until you land."); } } public static void Tick(Player player) { if (!_flyOffPending || (Object)(object)player == (Object)null) { return; } if (_active) { _flyOffPending = false; } else { if (!((Character)player).IsOnGround()) { return; } _flyOffPending = false; if (player.InDebugFlyMode() != _hadFly) { Silently(delegate { player.ToggleDebugFly(); }); ((Character)player).Message((MessageType)1, "$lb_creative_off", 0, (Sprite)null, false); Log.Info("Landed; flight off."); } } } private static void Silently(Action action) { _silent = true; try { action(); } finally { _silent = false; } } private static bool IsAdmin() { if (!((Object)(object)ZNet.instance == (Object)null)) { return SynchronizationManager.Instance.PlayerIsAdmin; } return true; } } [HarmonyPatch] internal static class HammerKeeper { private const string Key = "LetsBuild.Hammers"; [HarmonyPatch(typeof(Player), "Save")] [HarmonyPrefix] private static void Remember(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { int num = Count(((Humanoid)__instance).GetInventory()); if (num > 0) { __instance.m_customData["LetsBuild.Hammers"] = num.ToString(CultureInfo.InvariantCulture); } else { __instance.m_customData.Remove("LetsBuild.Hammers"); } } } [HarmonyPatch(typeof(Player), "Load")] [HarmonyPostfix] private static void Restore(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !__instance.m_customData.TryGetValue("LetsBuild.Hammers", out var value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return; } Inventory inventory = ((Humanoid)__instance).GetInventory(); int num = result - Count(inventory); if (num <= 0) { return; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("LetsBuild_Hammer") : null); if ((Object)(object)val == (Object)null) { Log.Warning("A builder's hammer is missing from the inventory, but the item is not registered."); return; } int num2 = 0; for (int i = 0; i < num; i++) { if (!inventory.AddItem(val, 1)) { break; } num2++; } if (num2 > 0) { Log.Info("Restored " + num2 + " builder's hammer(s) lost while the mod was not loaded."); ((Character)__instance).Message((MessageType)2, "$lb_hammer_restored", 0, (Sprite)null, false); } if (num2 < num) { ((Character)__instance).Message((MessageType)2, "$lb_hammer_no_room", 0, (Sprite)null, false); } } private static int Count(Inventory inventory) { int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (CreativeHammer.IsHammer(allItem)) { num += allItem.m_stack; } } return num; } } [HarmonyPatch] internal static class HintPanel { private sealed class Line { public string Text; public string[] Keys; public bool Combination; } private sealed class Row { public GameObject Root; public TMP_Text Label; public readonly List<GameObject> Parts = new List<GameObject>(); public string Shape; } private const float LineSpacing = 4f; private const float BarGap = 14f; private const float PartSpacing = 6f; private static RectTransform _panel; private static Image _picture; private static GameObject _labelTemplate; private static GameObject _keyTemplate; private static readonly List<Row> Rows = new List<Row>(); private static readonly List<Line> Lines = new List<Line>(); [HarmonyPatch(typeof(KeyHints), "Start")] [HarmonyPostfix] private static void Build(KeyHints __instance) { try { Create(__instance); } catch (Exception ex) { _panel = null; Log.Warning("Key hints could not be built from the game's hint bar: " + ex.Message); } } private static void Create(KeyHints vanilla) { //IL_0102: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) Rows.Clear(); GameObject buildHints = vanilla.m_buildHints; UIInputHint val = (((Object)(object)buildHints != (Object)null) ? buildHints.GetComponent<UIInputHint>() : null); Transform val2 = (((Object)(object)val != (Object)null && (Object)(object)val.m_mouseKeyboardHint != (Object)null) ? val.m_mouseKeyboardHint.transform : null); Transform val3 = (((Object)(object)val2 != (Object)null) ? val2.Find("Place") : null); Transform val4 = (((Object)(object)val3 != (Object)null) ? val3.Find("Text") : null); Transform val5 = (((Object)(object)val3 != (Object)null) ? val3.Find("key_bkg") : null); if ((Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val5.Find("Key") == (Object)null) { Log.Warning("The game's build hints are not built as expected; key hints are off."); return; } Transform val6 = LastEntry(val2); Transform val7 = (((Object)(object)val6 != (Object)null) ? LastVisible(val6) : buildHints.transform); GameObject val8 = new GameObject("LetsBuild_KeyHints", new Type[1] { typeof(RectTransform) }); _panel = (RectTransform)val8.transform; ((Transform)_panel).SetParent(val7, false); Vector3 lossyScale = buildHints.transform.lossyScale; Vector3 lossyScale2 = val7.lossyScale; ((Transform)_panel).localScale = new Vector3(Mathf.Approximately(lossyScale2.x, 0f) ? 1f : (lossyScale.x / lossyScale2.x), Mathf.Approximately(lossyScale2.y, 0f) ? 1f : (lossyScale.y / lossyScale2.y), 1f); _panel.anchorMin = new Vector2(1f, 1f); _panel.anchorMax = new Vector2(1f, 1f); _panel.pivot = new Vector2(1f, 0f); _panel.anchoredPosition = new Vector2(0f, 14f); Log.Info("Key hints hang on \"" + (((Object)(object)val6 != (Object)null) ? (((Object)val6).name + "/") : "") + ((Object)val7).name + "\"."); _picture = ((Component)val7).GetComponent<Image>(); val8.AddComponent<LayoutElement>().ignoreLayout = true; VerticalLayoutGroup obj = val8.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)8; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ContentSizeFitter obj2 = val8.AddComponent<ContentSizeFitter>(); obj2.horizontalFit = (FitMode)2; obj2.verticalFit = (FitMode)2; _labelTemplate = Template(((Component)val4).gameObject, "label"); _keyTemplate = Template(((Component)val5).gameObject, "key"); val8.SetActive(false); } private static Transform LastVisible(Transform entry) { for (int num = entry.childCount - 1; num >= 0; num--) { Transform child = entry.GetChild(num); if (((Component)child).gameObject.activeSelf && child is RectTransform && (Object)(object)((Component)child).GetComponent<Graphic>() != (Object)null) { return child; } } return entry; } private static Transform LastEntry(Transform keyboard) { for (int num = keyboard.childCount - 1; num >= 0; num--) { Transform child = keyboard.GetChild(num); if (((Component)child).gameObject.activeSelf && child is RectTransform) { return child; } } return null; } private static GameObject Template(GameObject source, string name) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0053: 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_005e: 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_0068: 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_007d: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(source, (Transform)(object)_panel, false); ((Object)val).name = "template_" + name; Localize[] componentsInChildren = val.GetComponentsInChildren<Localize>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } RectTransform val2 = (RectTransform)source.transform; RectTransform val3 = (RectTransform)val.transform; Rect rect = val2.rect; Vector2 size = ((Rect)(ref rect)).size; val3.anchorMin = new Vector2(0.5f, 0.5f); val3.anchorMax = new Vector2(0.5f, 0.5f); val3.pivot = new Vector2(0.5f, 0.5f); val3.sizeDelta = size; val.SetActive(false); return val; } public static void Tick() { if ((Object)(object)_panel == (Object)null) { return; } AlignToPicture(); Collect(); bool flag = Lines.Count > 0; if (((Component)_panel).gameObject.activeSelf != flag) { ((Component)_panel).gameObject.SetActive(flag); } if (!flag) { return; } while (Rows.Count < Lines.Count) { Rows.Add(NewRow()); } bool flag2 = false; for (int i = 0; i < Rows.Count; i++) { Row row = Rows[i]; bool flag3 = i < Lines.Count; if (row.Root.activeSelf != flag3) { row.Root.SetActive(flag3); flag2 = true; } if (flag3 && Fill(row, Lines[i])) { flag2 = true; } } if (flag2) { LayoutRebuilder.ForceRebuildLayoutImmediate(_panel); } } private static void AlignToPicture() { //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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_picture == (Object)null || (Object)(object)_panel == (Object)null) { return; } Rect rect = ((Graphic)_picture).rectTransform.rect; if (((Rect)(ref rect)).width <= 0f || ((Rect)(ref rect)).height <= 0f) { return; } Image picture = _picture; _picture = null; float num = ((Rect)(ref rect)).xMin; float num2 = ((Rect)(ref rect)).width; Sprite val = (((Object)(object)picture.overrideSprite != (Object)null) ? picture.overrideSprite : picture.sprite); Rect rect2; if ((Object)(object)val != (Object)null && picture.preserveAspect) { rect2 = val.rect; if (((Rect)(ref rect2)).height > 0f) { rect2 = val.rect; float width = ((Rect)(ref rect2)).width; rect2 = val.rect; float num3 = width / ((Rect)(ref rect2)).height; float num4 = ((Rect)(ref rect)).height * num3; if (num4 < ((Rect)(ref rect)).width) { num = ((Rect)(ref rect)).xMin + (((Rect)(ref rect)).width - num4) * ((Graphic)picture).rectTransform.pivot.x; num2 = num4; } } } float num5 = 0f; if ((Object)(object)val != (Object)null) { rect2 = val.rect; if (((Rect)(ref rect2)).width > 0f) { float num6 = float.MinValue; Vector2[] array; try { array = val.vertices; } catch (Exception) { array = (Vector2[])(object)new Vector2[0]; } Vector2[] array2 = array; foreach (Vector2 val2 in array2) { num6 = Mathf.Max(num6, val2.x); } if (num6 > float.MinValue) { float num7 = num6 * val.pixelsPerUnit + val.pivot.x; rect2 = val.rect; num5 = Mathf.Clamp01(1f - num7 / ((Rect)(ref rect2)).width); } } } float num8 = num + num2 * (1f - num5); float num9 = Mathf.Min(0f, num8 - ((Rect)(ref rect)).xMax); _panel.anchoredPosition = new Vector2(num9, _panel.anchoredPosition.y); string[] obj = new string[13] { "Key hints aligned to the drawn mouse: rect ", ((Rect)(ref rect)).width.ToString("0.#"), " x ", ((Rect)(ref rect)).height.ToString("0.#"), ", preserve aspect ", picture.preserveAspect.ToString(), ", sprite ", null, null, null, null, null, null }; object obj2; if (!((Object)(object)val != (Object)null)) { obj2 = "none"; } else { rect2 = val.rect; string text = ((Rect)(ref rect2)).width.ToString(); rect2 = val.rect; obj2 = text + " x " + ((Rect)(ref rect2)).height; } obj[7] = (string)obj2; obj[8] = ", right margin in sprite "; obj[9] = (num5 * 100f).ToString("0"); obj[10] = " %, offset "; obj[11] = num9.ToString("0.#"); obj[12] = "."; Log.Info(string.Concat(obj)); } private static Row NewRow() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown GameObject val = new GameObject("line", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)_panel, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)5; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ContentSizeFitter obj2 = val.AddComponent<ContentSizeFitter>(); obj2.horizontalFit = (FitMode)2; obj2.verticalFit = (FitMode)2; return new Row { Root = val, Label = NewLabel(val.transform) }; } private static TMP_Text NewLabel(Transform parent) { GameObject val = Object.Instantiate<GameObject>(_labelTemplate, parent, false); ((Object)val).name = "text"; val.SetActive(true); ContentSizeFitter[] components = val.GetComponents<ContentSizeFitter>(); for (int i = 0; i < components.Length; i++) { Object.DestroyImmediate((Object)(object)components[i]); } TMP_Text component = val.GetComponent<TMP_Text>(); component.textWrappingMode = (TextWrappingModes)0; return component; } private static bool SetText(TMP_Text label, string text) { //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_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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (label.text == text) { return false; } label.text = text; Vector2 preferredValues = label.GetPreferredValues(text); label.rectTransform.sizeDelta = new Vector2(Mathf.Ceil(preferredValues.x), Mathf.Max(label.rectTransform.sizeDelta.y, preferredValues.y)); return true; } private static bool Fill(Row row, Line line) { bool result = SetText(row.Label, line.Text); string text = (line.Combination ? "+" : "|") + string.Join("\u0001", line.Keys); if (text == row.Shape) { return result; } row.Shape = text; foreach (GameObject part in row.Parts) { part.SetActive(false); Object.Destroy((Object)(object)part); } row.Parts.Clear(); for (int i = 0; i < line.Keys.Length; i++) { if (i > 0 && line.Combination) { TMP_Text val = NewLabel(row.Root.transform); val.text = ""; SetText(val, "+"); row.Parts.Add(((Component)val).gameObject); } GameObject val2 = Object.Instantiate<GameObject>(_keyTemplate, row.Root.transform, false); ((Object)val2).name = "key"; val2.SetActive(true); ((Component)val2.transform.Find("Key")).GetComponent<TMP_Text>().text = line.Keys[i]; row.Parts.Add(val2); } return true; } private static void Collect() { Lines.Clear(); Player localPlayer = Player.m_localPlayer; if (!Settings.ShowKeyHints.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !((Character)localPlayer).InPlaceMode() || Hud.IsPieceSelectionVisible() || !Keys.GameHasInput(localPlayer)) { return; } Piece val = PlayerAccess.SelectedPiece(localPlayer); if ((Object)(object)val != (Object)null && PlantGrid.IsPlantPiece(val)) { if (Settings.PlantingEnabled.Value) { PlantLines(); } } else if (Settings.PrecisionEnabled.Value && PrecisionBuild.HoldsHammer(localPlayer)) { PrecisionLines(); } if (CreativeMode.Active) { Add("$lb_camera_toggle", Settings.CameraKey); } } private static void PlantLines() { int num = Mathf.Max(1, PlantGrid.PlannedCount); Either("$lb_rows: " + Settings.Rows.Value, Settings.MoreRowsKey, Settings.FewerRowsKey); Either("$lb_columns: " + Settings.Columns.Value + " (" + num + " $lb_plants)", Settings.MoreColumnsKey, Settings.FewerColumnsKey); Add("$lb_plant_snap: " + Texts.OnOff(Settings.SnapToPlants.Value), Settings.GridKey); if (Settings.BulkHarvest.Value) { List<string> list = new List<string>(Parts(Settings.BulkHarvestModifier)) { Texts.T("$KEY_Use") }; Lines.Add(new Line { Text = Texts.T("$lb_bulk_harvest"), Keys = list.ToArray(), Combination = true }); } if (!string.IsNullOrEmpty(PlantGrid.MainReason)) { Lines.Add(new Line { Text = "<color=#ff7a6a>" + Texts.T(PlantGrid.MainReason) + "</color>", Keys = new string[0] }); } } private static void PrecisionLines() { bool value = Settings.GridActive.Value; Add("$lb_grid: " + Texts.OnOff(value), Settings.GridKey); if (value) { Add("$lb_grid_size: " + PrecisionBuild.Metres(Settings.GridSize.Value), Settings.GridSizeKey); Add("$lb_rotation_step: " + PrecisionBuild.Degrees(Settings.RotationStep.Value), Settings.RotationKey); Add("$lb_snap_target: " + Texts.T(Settings.SnapToCellCenters.Value ? "$lb_snap_centres" : "$lb_snap_corners"), Settings.SnapTargetKey); } } private static void Add(string text, ConfigEntry<KeyboardShortcut> entry) { Lines.Add(new Line { Text = Texts.T(text), Keys = Parts(entry), Combination = true }); } private static void Either(string text, ConfigEntry<KeyboardShortcut> first, ConfigEntry<KeyboardShortcut> second) { List<string> list = new List<string>(); list.Add(string.Join(" + ", Parts(first))); list.Add(string.Join(" + ", Parts(second))); Lines.Add(new Line { Text = Texts.T(text), Keys = list.ToArray(), Combination = false }); } private static string[] Parts(ConfigEntry<KeyboardShortcut> entry) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_003c: 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) KeyboardShortcut value = entry.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0) { return new string[1] { "-" }; } List<string> list = new List<string>(); foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { list.Add(KeyName(modifier)); } list.Add(KeyName(((KeyboardShortcut)(ref value)).MainKey)); return list.ToArray(); } private unsafe static string KeyName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_001a: 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_0036: Expected I4, but got Unknown //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0036: 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_005a: Expected I4, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_005a: 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_0072: Expected I4, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_0134: 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_0124: Invalid comparison between Unknown and I4 if ((int)key <= 32) { if ((int)key == 13) { return Texts.T("$button_return"); } if ((int)key == 32) { return Texts.T("$button_space"); } } else { switch (key - 273) { case 0: return Texts.T("$lb_key_up"); case 1: return Texts.T("$lb_key_down"); case 3: return Texts.T("$lb_key_left"); case 2: return Texts.T("$lb_key_right"); } switch (key - 303) { case 1: return Texts.T("$button_lshift"); case 0: return Texts.T("$button_rshift"); case 5: return Texts.T("$button_lalt"); case 4: return Texts.T("$button_ralt"); case 3: return Texts.T("$button_lctrl"); case 2: return Texts.T("$button_rctrl"); } switch (key - 323) { case 0: return Texts.T("$button_mouse0"); case 1: return Texts.T("$button_mouse1"); case 2: return Texts.T("$button_mouse2"); } } if ((int)key >= 97 && (int)key <= 122) { return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } return ZInput.KeyCodeToDisplayName(key); } } internal static class Keys { private static readonly MethodInfo PlayerTakesInput = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); public static bool Down(ConfigEntry<KeyboardShortcut> entry) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = entry.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, false)) { return false; } return ModifiersHeld(value); } public static bool Held(ConfigEntry<KeyboardShortcut> entry) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = entry.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !ZInput.GetKey(((KeyboardShortcut)(ref value)).MainKey, false)) { return false; } return ModifiersHeld(value); } private static bool ModifiersHeld(KeyboardShortcut shortcut) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } public static bool GameHasInput(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (!(PlayerTakesInput == null)) { return (bool)PlayerTakesInput.Invoke(player, null); } return true; } } internal static class Log { private static ManualLogSource _source; public static void Init(ManualLogSource source) { _source = source; } public static void Info(string message) { ManualLogSource source = _source; if (source != null) { source.LogInfo((object)message); } } public static void Warning(string message) { ManualLogSource source = _source; if (source != null) { source.LogWarning((object)message); } } } [HarmonyPatch] internal static class GrowthInfo { private static readonly MethodInfo SincePlanted = AccessTools.Method(typeof(Plant), "TimeSincePlanted", (Type[])null, (Type[])null); private static readonly MethodInfo GrowTime = AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null); private static readonly FieldRef<Pickable, ZNetView> PickableView = AccessTools.FieldRefAccess<Pickable, ZNetView>("m_nview"); private static readonly FieldRef<Plant, ZNetView> PlantView = AccessTools.FieldRefAccess<Plant, ZNetView>("m_nview"); [HarmonyPatch(typeof(Plant), "GetHoverText")] [HarmonyPostfix] private static void PlantText(Plant __instance, ref string __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!Settings.ShowGrowthInfo.Value || string.IsNullOrEmpty(__result) || (int)__instance.GetStatus() != 0 || SincePlanted == null || GrowTime == null) { return; } ZNetView val = PlantView.Invoke(__instance); if (!((Object)(object)val == (Object)null) && val.IsValid()) { double num = (double)SincePlanted.Invoke(__instance, null); float num2 = (float)GrowTime.Invoke(__instance, null); if (!(num2 <= 0f)) { double num3 = (double)num2 - num; int num4 = Mathf.Clamp((int)(num / (double)num2 * 100.0), 0, 100); string text = ((num3 > 0.0) ? (num4 + " % " + Texts.T("$lb_grown") + ", " + Texts.T("$lb_ready_in") + " " + Duration(num3)) : ("100 % " + Texts.T("$lb_grown") + ", " + Texts.T("$lb_ready"))); __result = __result + "\n<color=#c8c8c8>" + text + "</color>"; } } } [HarmonyPatch(typeof(Pickable), "GetHoverText")] [HarmonyPostfix] private static void PickableText(Pickable __instance, ref string __result) { if (!Settings.ShowGrowthInfo.Value || !__instance.GetPicked() || __instance.m_respawnTimeMinutes <= 0f) { return; } ZNetView val = PickableView.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } long num = val.GetZDO().GetLong(ZDOVars.s_pickedTime, 0L); if (num > 1) { TimeSpan timeSpan = ZNet.instance.GetTime() - new DateTime(num); double num2 = (double)__instance.m_respawnTimeMinutes * 60.0 - timeSpan.TotalSeconds; if (!(num2 <= 0.0)) { string text = Localization.instance.Localize(__instance.GetHoverName()); __result = text + "\n<color=#c8c8c8>" + Texts.T("$lb_grows_back_in") + " " + Duration(num2) + "</color>"; } } } private static string Duration(double seconds) { TimeSpan timeSpan = TimeSpan.FromSeconds(Math.Max(0.0, seconds)); if (timeSpan.TotalHours >= 1.0) { return (int)timeSpan.TotalHours + " h " + timeSpan.Minutes.ToString("00") + " min"; } if (timeSpan.TotalMinutes >= 1.0) { return (int)timeSpan.TotalMinutes + " min"; } return timeSpan.Seconds + " s"; } } [HarmonyPatch] internal static class Harvest { private static readonly MethodInfo HoneyLevel = AccessTools.Method(typeof(Beehive), "GetHoneyLevel", (Type[])null, (Type[])null); private static readonly Dictionary<string, Piece> SeedFor = new Dictionary<string, Piece>(); private static ObjectDB _mappedFrom; private static bool _bulk; public static void Tick(Player player) { if ((Object)(object)player != (Object)null && Keys.GameHasInput(player) && Keys.Down(Settings.ReplantKey)) { Settings.ReplantOnHarvest.Value = !Settings.ReplantOnHarvest.Value; ((Character)player).Message((MessageType)1, "$lb_replant: " + Texts.OnOff(Settings.ReplantOnHarvest.Value), 0, (Sprite)null, false); } } [HarmonyPatch(typeof(Pickable), "Interact")] [HarmonyPrefix] private static void BeforePick(Pickable __instance, out bool __state) { __state = Ripe(__instance); } [HarmonyPatch(typeof(Pickable), "Interact")] [HarmonyPostfix] private static void AfterPick(Pickable __instance, Humanoid character, bool repeat, bool __state) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (!__state) { return; } Player val = (Player)(object)((character is Player) ? character : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { if (Settings.ReplantOnHarvest.Value) { Replant(val, __instance); } if (!repeat && !_bulk) { Bulk(val, ((Component)__instance).transform.position, Utils.GetPrefabName(((Component)__instance).gameObject)); } } } [HarmonyPatch(typeof(Beehive), "Interact")] [HarmonyPrefix] private static void BeforeHive(Beehive __instance, out bool __state) { __state = Honey(__instance) > 0; } [HarmonyPatch(typeof(Beehive), "Interact")] [HarmonyPostfix] private static void AfterHive(Beehive __instance, Humanoid character, bool repeat, bool __state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (__state && !repeat && !_bulk) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { Bulk(val, ((Component)__instance).transform.position, Utils.GetPrefabName(((Component)__instance).gameObject)); } } } private static bool Ripe(Pickable pickable) { if ((Object)(object)pickable != (Object)null && !pickable.GetPicked()) { return pickable.GetEnabled == 1; } return false; } private static int Honey(Beehive hive) { if (!(HoneyLevel != null)) { return 0; } return (int)HoneyLevel.Invoke(hive, null); } private static void Bulk(Player player, Vector3 centre, string kind) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!Settings.BulkHarvest.Value || !Keys.Held(Settings.BulkHarvestModifier)) { return; } bool value = Settings.HarvestSameKindOnly.Value; HashSet<int> hashSet = new HashSet<int>(); int num = 0; _bulk = true; try { Collider[] array = Physics.OverlapSphere(centre, Settings.HarvestRadius.Value, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { Pickable componentInParent = ((Component)val).GetComponentInParent<Pickable>(); if ((Object)(object)componentInParent != (Object)null) { if (hashSet.Add(((Object)((Component)componentInParent).gameObject).GetInstanceID()) && Ripe(componentInParent) && Harvestable(componentInParent) && (!value || Utils.GetPrefabName(((Component)componentInParent).gameObject) == kind)) { componentInParent.Interact((Humanoid)(object)player, false, false); num++; } continue; } Beehive componentInParent2 = ((Component)val).GetComponentInParent<Beehive>(); if ((Object)(object)componentInParent2 != (Object)null && hashSet.Add(((Object)((Component)componentInParent2).gameObject).GetInstanceID()) && Honey(componentInParent2) > 0 && (!value || Utils.GetPrefabName(((Component)componentInParent2).gameObject) == kind)) { componentInParent2.Interact((Humanoid)(object)player, false, false); num++; } } } finally { _bulk = false; } if (num > 0) { Log.Info("Bulk harvest picked " + num + " more."); } } private static bool Harvestable(Pickable pickable) { if (!IsGrowing(pickable)) { return pickable.m_harvestable; } return true; } public static bool IsGrowing(Pickable pickable) { string prefabName = Utils.GetPrefabName(((Component)pickable).gameObject); if (!SeedMap().ContainsKey(prefabName)) { return Plantables.IsWildPlant(prefabName); } return true; } private static void Replant(Player player, Pickable pickable) { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_0088: Unknown result type (might be due to invalid IL or missing references) if (!SeedMap().TryGetValue(Utils.GetPrefabName(((Component)pickable).gameObject), out var value) || (Object)(object)value == (Object)null) { return; } Vector3 position = ((Component)pickable).transform.position; if (Location.IsInsideNoBuildLocation(position) || !PrivateArea.CheckAccess(position, 0f, false, false)) { return; } bool flag = player.NoCostCheat(); if (flag || player.HaveRequirements(value, (RequirementMode)0)) { bool flag2 = (((Humanoid)player).GetInventory().ItemCheated(value.m_resources, -1, true) || flag) && !PlayerProfile.s_bypassCheatChecks; if (!flag && !ZoneSystem.instance.GetGlobalKey(value.FreeBuildKey())) { player.ConsumeResources(value.m_resources, 0, -1, 1); } Quaternion val = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); player.PlacePiece(value, position, val, false, flag2); } } private static Dictionary<string, Piece> SeedMap() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)_mappedFrom) { return SeedFor; } SeedFor.Clear(); _mappedFrom = instance; GameObject itemPrefab = instance.GetItemPrefab("Cultivator"); PieceTable val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces); if ((Object)(object)val == (Object)null) { Log.Warning("Cultivator piece table not found; replanting is unavailable."); return SeedFor; } foreach (GameObject piece in val.m_pieces) { Plant val2 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Plant>() : null); Piece val3 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { continue; } GameObject[] grownPrefabs = val2.m_grownPrefabs; foreach (GameObject val4 in grownPrefabs) { if ((Object)(object)val4 != (Object)null && (Object)(object)val4.GetComponent<Pickable>() != (Object)null && !SeedFor.ContainsKey(((Object)val4).name)) { SeedFor[((Object)val4).name] = val3; } } } return SeedFor; } } [HarmonyPatch] internal static class Plantables { private enum Kind { Bush, Mushroom, Flower } private sealed class SaplingDef { public string Name; public string Token; public Biome Home; public string[] Grows; public (string item, int amount)[] Cost; public bool TolerateHeat; } private static readonly Dictionary<string, Kind> Wild = new Dictionary<string, Kind> { { "RaspberryBush", Kind.Bush }, { "BlueberryBush", Kind.Bush }, { "CloudberryBush", Kind.Bush }, { "LingonberryBush", Kind.Bush }, { "Pickable_Mushroom", Kind.Mushroom }, { "Pickable_Mushroom_yellow", Kind.Mushroom }, { "Pickable_Mushroom_blue", Kind.Mushroom }, { "Pickable_Thistle", Kind.Flower }, { "Pickable_Dandelion", Kind.Flower }, { "Pickable_SmokePuff", Kind.Flower }, { "Pickable_Fiddlehead", Kind.Flower } }; private const Biome Temperate = (Biome)25; private static readonly SaplingDef[] Saplings = new SaplingDef[4] { new SaplingDef { Name = "LetsBuild_Sapling_Ancient", Token = "lb_sapling_ancient", Home = (Biome)2, Grows = new string[1] { "SwampTree1" }, Cost = new(string, int)[1] { ("AncientSeed", 1) } }, new SaplingDef { Name = "LetsBuild_Sapling_Ygga", Token = "lb_sapling_ygga", Home = (Biome)512, Grows = new string[3] { "YggaShoot1", "YggaShoot2", "YggaShoot3" }, Cost = new(string, int)[1] { ("Sap", 1) } }, new SaplingDef { Name = "LetsBuild_Sapling_AutumnBirch", Token = "lb_sapling_autumnbirch", Home = (Biome)0, Grows = new string[2] { "Birch1_aut", "Birch2_aut" }, Cost = new(string, int)[1] { ("BirchSeeds", 1) } }, new SaplingDef { Name = "LetsBuild_Sapling_Ashwood", Token = "lb_sapling_ashwood", Home = (Biome)32, Grows = new string[4] { "AshlandsTree3", "AshlandsTree4", "AshlandsTree5", "AshlandsTree6_big" }, Cost = new(string, int)[2] { ("BeechSeeds", 1), ("SulfurStone", 1) }, TolerateHeat = true } }; private static readonly HashSet<string> OurWildPieces = new HashSet<string>(); private static readonly List<Piece> OurSaplings = new List<Piece>(); private static readonly Dictionary<string, bool> CropCache = new Dictionary<string, bool>(); private static readonly Dictionary<Piece, bool> CultivatedOnly = new Dictionary<Piece, bool>(); public static bool IsWildPlant(string prefabName) { return Wild.ContainsKey(prefabName); } public static void Register() { PrefabManager.OnVanillaPrefabsAvailable += CreateSaplings; PieceManager.OnPiecesRegistered += ApplyWildPlants; Settings.File.SettingChanged += delegate(object _, SettingChangedEventArgs e) { if (Settings.IsServerRule(e.ChangedSetting)) { ApplyAll(); } }; SynchronizationManager.OnConfigurationSynchronized += delegate { ApplyAll(); }; } private static void ApplyAll() { ApplyWildPlants(); ApplySaplings(); } private static void ApplyWildPlants() { //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Expected O, but got Unknown PieceTable val = CultivatorTable(); if ((Object)(object)val == (Object)null) { return; } Piece val2 = PieceOf("sapling_carrot"); foreach (KeyValuePair<string, Kind> item in Wild) { GameObject prefab = PrefabManager.Instance.GetPrefab(item.Key); Pickable val3 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Pickable>() : null); ItemDrop val4 = (((Object)(object)val3 != (Object)null && (Object)(object)val3.m_itemPrefab != (Object)null) ? val3.m_itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val4 == (Object)null) { Log.Warning("Cannot make " + item.Key + " plantable; the game has no such pickable."); continue; } Piece val5 = prefab.GetComponent<Piece>(); bool flag = (Object)(object)val5 != (Object)null; if ((Object)(object)val5 == (Object)null) { val5 = prefab.AddComponent<Piece>(); } if (OurWildPieces.Add(item.Key)) { Log.Info("Plantable: " + item.Key + (flag ? " (had a piece already)" : "") + ", grows back after " + val3.m_respawnTimeMinutes + " min."); } string name = val4.m_itemData.m_shared.m_name; val5.m_name = ((item.Value == Kind.Bush) ? (name + " ($lb_bush)") : name); val5.m_description = "$lb_wild_plant_desc"; val5.m_icon = val4.m_itemData.GetIcon(); val5.m_category = (PieceCategory)0; val5.m_groundOnly = true; val5.m_clipEverything = true; val5.m_randomInitBuildRotation = true; val5.m_canBeRemoved = true; if ((Object)(object)val2 != (Object)null) { val5.m_placeEffect = val2.m_placeEffect; } val5.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = val4, m_amount = Cost(item.Value), m_recover = false } }; bool flag2 = val.m_pieces.Contains(prefab); if (Settings.PlantWildPlants.Value && !flag2) { val.m_pieces.Add(prefab); } else if (!Settings.PlantWildPlants.Value && flag2) { val.m_pieces.Remove(prefab); } } } private static int Cost(Kind kind) { return kind switch { Kind.Bush => Settings.BushCost.Value, Kind.Mushroom => Settings.MushroomCost.Value, _ => Settings.FlowerCost.Value, }; } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] [HarmonyPostfix] private static void OnlyPlanted(Piece piece, ref bool __result) { if (__result && (Object)(object)piece != (Object)null && OurWildPieces.Contains(Utils.GetPrefabName(((Component)piece).gameObject)) && !piece.IsPlacedByPlayer()) { __result = false; } } private static void CreateSaplings() { //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= CreateSaplings; SaplingDef[] saplings = Saplings; foreach (SaplingDef saplingDef in saplings) { List<GameObject> list = new List<GameObject>(); string[] grows = saplingDef.Grows; foreach (string text in grows) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); if ((Object)(object)prefab != (Object)null) { list.Add(prefab); } else { Log.Warning(saplingDef.Name + ": the game has no " + text + "."); } } ItemDrop val = ItemOf(saplingDef.Cost[0].item); if (list.Count == 0 || (Object)(object)val == (Object)null) { Log.Warning(saplingDef.Name + " not created; its tree or seed is missing."); continue; } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(saplingDef.Name, "Beech_Sapling"); Plant val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Plant>() : null); if ((Object)(object)val3 == (Object)null) { Log.Warning(saplingDef.Name + " not created; the beech sapling could not be copied."); continue; } val3.m_name = "$" + saplingDef.Token; val3.m_grownPrefabs = list.ToArray(); val3.m_biome = (Biome)(saplingDef.Home | 0x19); val3.m_tolerateHeat = saplingDef.TolerateHeat; List<RequirementConfig> list2 = new List<RequirementConfig>(); (string, int)[] cost = saplingDef.Cost; for (int j = 0; j < cost.Length; j++) { var (item, amount) = cost[j]; list2.Add(new RequirementConfig { Item = item, Amount = amount, Recover = true }); } CustomPiece val4 = new CustomPiece(val2, false, new PieceConfig { Name = "$" + saplingDef.Token, Description = "$" + saplingDef.Token + "_desc", PieceTable = PieceTables.Cultivator, Category = PieceCategories.Misc, Icon = val.m_itemData.GetIcon(), Requirements = list2.ToArray() }); if (PieceManager.Instance.AddPiece(val4)) { OurSaplings.Add(val4.Piece); } } ApplySaplings(); Log.Info(OurSaplings.Count + " new saplings registered."); } private static void ApplySaplings() { foreach (Piece ourSapling in OurSaplings) { if ((Object)(object)ourSapling != (Object)null) { ourSapling.m_enabled = Settings.ExtraSaplings.Value; } } } public static Biome Biome(Plant plant) { //IL_003c: 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) bool flag = IsCrop(plant); if ((flag && Settings.CropsAnyBiome.Value) || (!flag && Settings.SaplingsAnyBiome.Value)) { return (Biome)895; } return Original(plant)?.m_biome ?? plant.m_biome; } public static bool NeedsCultivation(Plant plant) { if (Settings.NeedCultivatedGround.Value) { return Original(plant)?.m_needCultivatedGround ?? plant.m_needCultivatedGround; } return false; } private static Plant Original(Plant plant) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(Utils.GetPrefabName(((Component)plant).gameObject)) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Plant>(); } private static bool IsCrop(Plant plant) { string prefabName = Utils.GetPrefabName(((Component)plant).gameObject); if (!CropCache.TryGetValue(prefabName, out var value)) { value = plant.m_grownPrefabs != null && plant.m_grownPrefabs.Length != 0 && (Object)(object)plant.m_grownPrefabs[0] != (Object)null && (Object)(object)plant.m_grownPrefabs[0].GetComponent<Pickable>() != (Object)null; CropCache[prefabName] = value; } return value; } [HarmonyPatch(typeof(Plant), "UpdateHealth")] [HarmonyPrefix] private static void Rules(Plant __instance) { //IL_0002: 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) __instance.m_biome = Biome(__instance); __instance.m_needCultivatedGround = NeedsCultivation(__instance); } [HarmonyPatch(typeof(Plant), "HaveRoof")] [HarmonyPrefix] private static bool Roof(ref bool __result) { if (Settings.NeedOpenSky.Value) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Plant), "HaveGrowSpace")] [HarmonyPrefix] private static bool Space(ref bool __result) { if (Settings.NeedGrowSpace.Value) { return true; } __result = true; return false; } [HarmonyPatch(typeof(Plant), "GetGrowTime")] [HarmonyPostfix] private static void GrowTime(Plant __instance, ref float __result) { __result *= (IsCrop(__instance) ? Settings.CropGrowTime.Value : Settings.SaplingGrowTime.Value); } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] [HarmonyPrefix] private static void GroundRule(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Piece val = PlayerAccess.SelectedPiece(__instance); if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponent<Plant>() == (Object)null)) { if (!CultivatedOnly.TryGetValue(val, out var value)) { value = val.m_cultivatedGroundOnly; CultivatedOnly[val] = value; } bool cultivatedGroundOnly = (val.m_cultivatedGroundOnly = value && Settings.NeedCultivatedGround.Value); GameObject val2 = PlayerAccess.Ghost.Invoke(__instance); Piece val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Piece>() : null); if ((Object)(object)val3 != (Object)null) { val3.m_cultivatedGroundOnly = cultivatedGroundOnly; } } } private static PieceTable CultivatorTable() { ItemDrop val = ItemOf("Cultivator"); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_itemData.m_shared.m_buildPieces; } private static ItemDrop ItemOf(string name) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null); if ((Object)(object)val == (Object)null) { val = PrefabManager.Instance.GetPrefab(name); } if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<ItemDrop>(); } private static Piece PieceOf(string name) { GameObject prefab = PrefabManager.Instance.GetPrefab(name); if (!((Object)(object)prefab != (Object)null)) { return null; } return prefab.GetComponent<Piece>(); } } [HarmonyPatch] internal static class PlantGrid { private struct Extra { public GameObject Ghost; public float Yaw; public Vector3 Position; public Quaternion Rotation; public bool Valid; } private struct Job { public Piece Piece; public Vector3 Position; public Quaternion Rotation; } private static readonly List<Extra> Extras = new List<Extra>(); private static readonly Queue<Job> Jobs = new Queue<Job>(); private static int _sourceId; private static int _sourceFrame; private static int _placeMask; private static float _gridAngle; private static bool _angleSet; private static int _lastCounter; private static float _lastStep; private static bool _counterReset = true; public static int PlannedCount { get; private set; } public static string MainReason { get; private set; } = ""; public static bool IsPlantPiece(Piece piece) { if ((Object)(object)piece != (Object)null) { if (!((Object)(object)((Component)piece).GetComponent<Plant>() != (Object)null)) { return (Object)(object)((Component)piece).GetComponent<Pickable>() != (Object)null; } return true; } return false; } private static bool Active(Player player) { if (Settings.PlantingEnabled.Value && (Object)(object)player != (Object)null && ((Character)player).InPlaceMode()) { return IsPlantPiece(PlayerAccess.SelectedPiece(player)); } return false; } public static void Tick(Player player) { if ((Object)(object)player == (Object)null) { Jobs.Clear(); return; } if (Active(player) && Keys.GameHasInput(player) && !Hud.IsPieceSelectionVisible()) { ReadKeys(player); } PlaceQueued(player); } private static void ReadKeys(Player player) { if (Keys.Down(Settings.MoreRowsKey)) { Resize(player, Settings.Rows, 1); } if (Keys.Down(Settings.FewerRowsKey)) { Resize(player, Settings.Rows, -1); } if (Keys.Down(Settings.MoreColumnsKey)) { Resize(player, Settings.Columns, 1); } if (Keys.Down(Settings.FewerColumnsKey)) { Resize(player, Settings.Columns, -1); } if (Keys.Down(Settings.GridKey)) { Settings.SnapToPlants.Value = !Settings.SnapToPlants.Value; ((Character)player).Message((MessageType)1, "$lb_plant_snap: " + Texts.OnOff(Settings.SnapToPlants.Value), 0, (Sprite)null, false); } } private static void Resize(Player player, ConfigEntry<int> entry, int delta) { int value = Settings.MaxPlantsPerClick.Value; int num = ((entry == Settings.Rows) ? Settings.Columns.Value : Settings.Rows.Value); int num2 = Mathf.Clamp(entry.Value + delta, 1, 50); if (num2 * num > value) { num2 = Mathf.Max(1, value / Mathf.Max(1, num)); } entry.Value = num2; ((Character)player).Message((MessageType)1, "$lb_rows " + Settings.Rows.Value + " × $lb_columns " + Settings.Columns.Value, 0, (Sprite)null, false); } private static void PlaceQueued(Player player) { int value = Settings.PlantsPerFrame.Value; while (value-- > 0 && Jobs.Count > 0) { Job job = Jobs.Peek(); if (!PlaceOne(player, job)) { Jobs.Clear(); break; } Jobs.Dequeue(); } } private static bool PlaceOne(Player player, Job job) { //IL_0021: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) if (((Character)player).IsDead() || !((Character)player).InPlaceMode() || (Object)(object)job.Piece == (Object)null) { return false; } if (Location.IsInsideNoBuildLocation(job.Position) || !PrivateArea.CheckAccess(job.Position, 0f, false, false)) { return true; } bool flag = player.NoCostCheat(); if (!flag && !player.HaveRequirements(job.Piece, (RequirementMode)0)) { ((Character)player).Message((MessageType)2, "$msg_missingrequirement", 0, (Sprite)null, false); return false; } ItemData rightItem = PlayerAccess.GetRightItem(player); if (rightItem == null) { return false; } float buildStamina = PlayerAccess.GetBuildStamina(player); if (Settings.PlantingUsesStamina.Value && !((Character)player).HaveStamina(buildStamina)) { Hud.instance.StaminaBarEmptyFlash(); ((Character)player).Message((MessageType)1, "$lb_planting_stopped", 0, (Sprite)null, false); return false; } if (Settings.PlantingUsesDurability.Value && rightItem.m_shared.m_useDurability && rightItem.m_durability <= 0f) { ((Character)player).Message((MessageType)1, "$lb_planting_stopped", 0, (Sprite)null, false); return false; } bool flag2 = (((Humanoid)player).GetInventory().ItemCheated(job.Piece.m_resources, -1, true) || flag) && !PlayerProfile.s_bypassCheatChecks; if (!flag && !ZoneSystem.instance.GetGlobalKey(job.Piece.FreeBuildKey())) { player.ConsumeResources(job.Piece.m_resources, 0, -1, 1); } player.PlacePiece(job.Piece, job.Position, job.Rotation, false, flag2); if (Settings.PlantingUsesStamina.Value) { ((Character)player).UseStamina(buildStamina); } if (Settings.PlantingUsesDurability.Value && rightItem.m_shared.m_useDurability) { rightItem.m_durability = Mathf.Max(0f, rightItem.m_durability - PlayerAccess.GetPlaceDurability(player, rightItem) * Game.m_durabilityRate); } PieceTable val = PlayerAccess.BuildPieces.Invoke(player); if ((Object)(object)val != (Object)null && (int)val.m_skill != 0) { ((Character)player).RaiseSkill(val.m_skill, 1f); } return true; } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] [HarmonyPostfix] private static void AfterGhost(Player __instance) { //IL_00d8: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } _placeMask = PlayerAccess.PlaceRayMask.Invoke(__instance); GameObject val = PlayerAccess.Ghost.Invoke(__instance); Piece val2 = PlayerAccess.SelectedPiece(__instance); if (!Active(__instance) || (Object)(object)val == (Object)null || !val.activeSelf || (int)PlayerAccess.Status.Invoke(__instance) == 12) { HideExtras(); PlannedCount = 0; MainReason = ""; return; } TrackTurn(__instance); float spacing = PlantRules.Spacing(((Component)val2).gameObject); float lift = GhostLift(val); Directions(val, out var forward, out var right); bool moved = false; if (Settings.SnapToPlants.Value && !AltHeld() && TrySnap(val, spacing, lift, out var forward2, out var right2, out var step)) { moved = true; forward = forward2; right = right2; spacing = step; } RecheckMain(__instance, val, val2, moved); LayOut(__instance, val, val2, spacing, lift, forward, right); } [HarmonyPatch(typeof(Player), "TryPlacePiece")] [HarmonyPostfix] private static void Placed(Player __instance, Piece piece, bool __result) { //IL_0069: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Active(__instance)) { return; } foreach (Extra extra in Extras) { if ((Object)(object)extra.Ghost != (Object)null && extra.Ghost.activeSelf && extra.Valid) { Jobs.Enqueue(new Job { Piece = piece, Position = extra.Position, Rotation = extra.Rotation }); } } } private static bool TrySnap(GameObject ghost, float spacing, float lift, out Vector3 forward, out Vector3 right, out float step) { //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_0019: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) Directions(ghost, out forward, out right); step = spacing; Vector3 position = ghost.transform.position; List<Transform> list = PlantsAround(position, spacing * 2.5f + 1f); if (list.Count == 0) { return false; } Transform val = null; float num = float.MaxValue; foreach (Transform item in list) { float num2 = FlatDistance(item.position, position); if (num2 < num) { num = num2; val = item; } } step = Mathf.Max(spacing, PlantRules.Spacing(((Component)val).gameObject)); if (num > step * 2f) { return false; } foreach (Transform item2 in PlantsAround(val.position, step * 1.3f)) { if (!((Object)(object)item2 == (Object)(object)val) && Mathf.Abs(FlatDistance(item2.position, val.position) - step) <= step * 0.25f) { Vector3 val2 = item2.position - val.position; val2.y = 0f; forward = ((Vector3)(ref val2)).normalized; right = Vector3.Cross(Vector3.up, forward); break; } } FaceGhost(ghost, ref forward, ref right); Vector3 val3 = position - val.position; val3.y = 0f; int num3 = Mathf.RoundToInt(Vector3.Dot(val3, forward) / step); int num4 = Mathf.RoundToInt(Vector3.Dot(val3, right) / step); if (num3 == 0 && num4 == 0) { float num5 = Vector3.Dot(val3, forward); float num6 = Vector3.Dot(val3, right); if (Mathf.Abs(num5) >= Mathf.Abs(num6)) { num3 = ((num5 >= 0f) ? 1 : (-1)); } else { num4 = ((num6 >= 0f) ? 1 : (-1)); } } Vector3 val4 = val.position + forward * ((float)num3 * step) + right * ((float)num4 * step); if (FlatDistance(val4, position) > step * 1.5f || !Ground(val4, out var ground, out var _)) { return false; } ghost.transform.position = ground + Vector3.up * lift; return true; } private static List<Transform> PlantsAround(Vector3 centre, float radius) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); HashSet<int> hashSet = new HashSet<int>(); int num = LayerMask.NameToLayer("ghost"); Collider[] array = Physics.OverlapSphere(centre, radius, -1, (QueryTriggerInteraction)2); foreach (Collider val in array) { if (((Component)val).gameObject.layer == num) { continue; } Component componentInParent = (Component)(object)((Component)val).GetComponentInParent<Plant>(); if ((Object)(object)componentInParent == (Object)null) { componentInParent = (Component)(object)((Component)val).GetComponentInParent<Pickable>(); } if ((Object)(object)componentInParent == (Object)null || !hashSet.Add(((Object)componentInParent.gameObject).GetInstanceID())) { continue; } Pickable val2 = (Pickable)(object)((componentInParent is Pickable) ? componentInParent : null); if (val2 == null || Harvest.IsGrowing(val2)) { ZNetView component = componentInParent.GetComponent<ZNetView>(); if (component != null && component.IsValid()) { list.Add(componentInParent.transform); } } } return list; } [HarmonyPatch(typeof(Player), "PlacePiece")] [HarmonyPostfix] private static void GameRandomised() { _counterReset = true; } [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] [HarmonyPostfix] private static void GhostRebuilt() { _counterReset = true; } private static void TrackTurn(Player player) { if (!_angleSet && (Object)(object)GameCamera.instance != (Object)null) { _gridAngle = 0f; _angleSet = true; } int num = PlayerAccess.Rotation.Invoke(player); float num2 = PlayerAccess.RotationDegrees.Invoke(player); if (_counterReset || !Mathf.Approximately(num2, _lastStep)) { _counterReset = false; } else if (num != _lastCounter) { _gridAngle += (float)(num - _lastCounter) * num2; } _lastCounter = num; _lastStep = num2; } private static Vector3 GridFacing() { //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_0019: Unknown result type (might be due to invalid IL or missing references) return Quaternion.Euler(0f, _gridAngle, 0f) * Vector3.forward; } private static void FaceGhost(GameObject ghost, ref Vector3 forward, ref Vector3 right) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_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_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_0033: 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_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_0052: 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_0065: 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_006b: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00a7: 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_0081: Unknown result type (might be due to invalid IL or missing references) Vector3 val = GridFacing(); Vector3 val2 = forward; float num = float.MinValue; Vector3[] array = (Vector3[])(object)new Vector3[4] { forward, -forward, right, -right }; foreach (Vector3 val3 in array) { float num2 = Vector3.Dot(val3, ((Vector3)(ref val)).normalized); if (num2 > num) { num = num2; val2 = val3; } } forward = val2; right = Vector3.Cross(Vector3.up, forward); } private static void Directions(GameObject ghost, out Vector3 forward, out Vector3 right) { //IL_0037: 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_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_0052: 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_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) //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_0028: Unknown result type (might be due to invalid IL or missing references) if (Settings.AlignToWorld.Value) { forward = Vector3.forward; right = Vector3.Cross(Vector3.up, forward); FaceGhost(ghost, ref forward, ref right); } else { forward = GridFacing(); right = Vector3.Cross(Vector3.up, forward); } } private static void RecheckMain(Player player, GameObject ghost, Piece piece, bool moved) { //IL_000c: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_001c: 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_002e: 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_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_0025: 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_00a5: Expected I4, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 //IL_0061: 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_0069: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) PlacementStatus val = PlayerAccess.Status.Invoke(player); Vector3 position = ghost.transform.position; if (moved && IsPositional(val)) { val = (PlacementStatus)0; } if ((int)val == 0 && moved) { Ground(position, out var _, out var heightmap); val = PlacementRules(piece, position, heightmap); } MainReason = ""; if ((int)val == 0 && Settings.PreventInvalidPlanting.Value) { Status val2 = PlantRules.Check(((Component)piece).gameObject, position); if ((int)val2 != 0) { val = (PlacementStatus)1; MainReason = PlantRules.Reason(val2); } else if (PlantRules.Occupied(((Component)piece).gameObject, position)) { val = (PlacementStatus)1; MainReason = PlantRules.Reason((Status)2); } } PlayerAccess.Status.Invoke(player) = (PlacementStatus)(int)val; Piece component = ghost.GetComponent<Piece>(); if (component != null) { component.SetInvalidPlacementHeightlight((int)val > 0); } } private static bool IsPositional(PlacementStatus status) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if ((int)status != 9 && (int)status != 10 && (int)status != 3 && (int)status != 4) { return (int)status == 8; } return true; } private static PlacementStatus PlacementRules(Piece piece, Vector3 position, Heightmap heightmap) { //IL_0000: 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) //IL_0099: 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_00a0: 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_00a7: 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_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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unkno