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.7.7
plugins/LetsBuild.dll
Decompiled 3 weeks 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.7.7.0")] [assembly: AssemblyInformationalVersion("0.7.7+0ae45d386b853d81f06bfff27042dd0020b0a2c9")] [assembly: AssemblyProduct("Lets Build")] [assembly: AssemblyTitle("LetsBuild")] [assembly: AssemblyVersion("0.7.7.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 { internal static class AreaRepair { private static readonly MethodInfo HoveringPiece = AccessTools.Method(typeof(Player), "GetHoveringPiece", (Type[])null, (Type[])null); private static int _mask; private static bool _repairing; public static void Patch(Harmony harmony) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00b6: Expected O, but got Unknown //IL_00b6: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Player), "Repair", new Type[2] { typeof(ItemData), typeof(Piece) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "CheckCanRemovePiece", (Type[])null, (Type[])null); if (methodInfo == null || HoveringPiece == null) { Log.Warning("Area repair is not available: the game has no Player.Repair or GetHoveringPiece as expected."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(AreaRepair), "StartRepair", (Type[])null), new HarmonyMethod(typeof(AreaRepair), "RepairAround", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(AreaRepair), "EndRepair", (Type[])null), (HarmonyMethod)null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(AreaRepair), "NoStationNeeded", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.Warning("Repairing still needs a crafting station: the game has no CheckCanRemovePiece as expected."); } } private static void StartRepair(Player __instance) { _repairing = Settings.AreaRepair.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && PrecisionBuild.HoldsHammer(__instance); } private static void EndRepair() { _repairing = false; } private static bool NoStationNeeded(ref bool __result) { if (!_repairing) { return true; } __result = true; return false; } private static void RepairAround(Player __instance, ItemData toolItem) { //IL_0096: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: 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_014d: Unknown result type (might be due to invalid IL or missing references) if (!Settings.AreaRepair.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || toolItem == null || !((Character)__instance).InPlaceMode() || !PrecisionBuild.HoldsHammer(__instance)) { return; } object? obj = HoveringPiece.Invoke(__instance, null); Piece val = (Piece)((obj is Piece) ? obj : null); if ((Object)(object)val == (Object)null) { return; } if (_mask == 0) { _mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "vehicle" }); } Vector3 position = ((Component)val).transform.position; HashSet<int> hashSet = new HashSet<int> { ((Object)((Component)val).gameObject).GetInstanceID() }; List<(WearNTear, Piece, float)> list = new List<(WearNTear, Piece, float)>(); Collider[] array = Physics.OverlapSphere(position, Settings.RepairRadius.Value, _mask); for (int i = 0; i < array.Length; i++) { WearNTear componentInParent = ((Component)array[i]).GetComponentInParent<WearNTear>(); if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(((Object)((Component)componentInParent).gameObject).GetInstanceID())) { Piece component = ((Component)componentInParent).GetComponent<Piece>(); ZNetView component2 = ((Component)componentInParent).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && component2.IsValid() && !(componentInParent.GetHealthPercentage() >= 1f)) { list.Add((componentInParent, component, Vector3.Distance(position, ((Component)componentInParent).transform.position))); } } } list.Sort(((WearNTear wear, Piece piece, float distance) a, (WearNTear wear, Piece piece, float distance) b) => a.distance.CompareTo(b.distance)); bool value = Settings.RepairCosts.Value; float buildStamina = PlayerAccess.GetBuildStamina(__instance); float attackEitr = toolItem.m_shared.m_attack.m_attackEitr; float num = toolItem.m_shared.m_useDurabilityDrain * Game.m_durabilityRate; int num2 = 0; foreach (var item2 in list) { WearNTear item = item2.Item1; if (!PrivateArea.CheckAccess(((Component)item).transform.position, 0f, false, false)) { continue; } if (value && (!((Character)__instance).HaveStamina(buildStamina) || !((Character)__instance).HaveEitr(attackEitr) || (toolItem.m_shared.m_useDurability && toolItem.m_durability <= 0f))) { break; } if (!item.Repair()) { continue; } num2++; if (value) { ((Character)__instance).UseStamina(buildStamina); ((Character)__instance).UseEitr(attackEitr); if (toolItem.m_shared.m_useDurability) { toolItem.m_durability = Mathf.Max(0f, toolItem.m_durability - num); } } } if (num2 > 0) { ((Character)__instance).Message((MessageType)1, "$lb_repaired_around: " + num2, 0, (Sprite)null, false); } } } [HarmonyPatch] internal static class BuildCamera { private const float Speed = 10f; private const float MaxPitch = 89f; private const float MaxReach = 64f; private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude"); private static bool _loose; private static bool _carry; 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.Holding || (_carry && !CreativeMode.IsAdmin()))) { Fix(player); } else { if ((Object)(object)player == (Object)null || !CreativeMode.Holding) { 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) { return Keys.GameHasInput(player); } 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; _carry = CreativeMode.IsAdmin(); if (_carry) { Hide(player); } _loose = true; ((Character)player).Message((MessageType)1, "$lb_camera_loose", 0, (Sprite)null, false); } } private static void Fix(Player player) { //IL_0039: 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; } if (_carry) { Show(); if (!player.InDebugFlyMode()) { Teleport(player, _start); MaxAirAltitude.Invoke((Character)(object)player) = _start.y; } } _carry = false; ((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 Leash(Player player) { //IL_0021: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)((Character)player).m_eye != (Object)null) ? ((Character)player).m_eye.position : ((Component)player).transform.position); Vector3 val2 = _position - val; if (((Vector3)(ref val2)).sqrMagnitude > 4096f) { _position = val + ((Vector3)(ref val2)).normalized * 64f; } } 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (_loose) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && !_carry) { Leash(localPlayer); } ((Component)__instance).transform.position = _position; ((Component)__instance).transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f); if ((Object)(object)localPlayer != (Object)null && _carry) { 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"; private static Recipe _recipe; public static void Register() { PrefabManager.OnVanillaPrefabsAvailable += Create; Settings.Craftable.SettingChanged += delegate { ApplyCraftable(); }; SynchronizationManager.OnConfigurationSynchronized += delegate { ApplyCraftable(); }; } private static void ApplyCraftable() { if ((Object)(object)_recipe != (Object)null) { _recipe.m_enabled = Settings.Craftable.Value; } } 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0085: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Create; ItemConfig val = new ItemConfig(); val.Enabled = Settings.Craftable.Value; 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 = new CustomItem("LetsBuild_Hammer", "Hammer", val2); 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); CustomRecipe recipe = val3.Recipe; _recipe = ((recipe != null) ? recipe.Recipe : null); ApplyCraftable(); Log.Info("Builder's hammer registered; " + (Settings.Craftable.Value ? "craftable at the workbench." : "not craftable now, spawn it with \"spawn LetsBuild_Hammer\".") + (((Object)(object)_recipe == (Object)null) ? " (No recipe could be made.)" : "")); } 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; private static bool _toldAdminOnly; private static bool _holding; public static bool Active => _active; public static bool Holding => _holding; public static void Register() { SynchronizationManager.OnAdminStatusChanged += AdminChanged; } private static void AdminChanged() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && _holding) { if (!IsAdmin()) { Leave(localPlayer); } else if (Settings.CreativeActive.Value) { Enter(localPlayer); } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] [HarmonyPostfix] private static void Equipped(Humanoid __instance, ItemData item, bool __result) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (__result && IsOurs(__instance, item)) { _holding = true; if (Settings.CreativeActive.Value) { Enter((Player)__instance); } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] [HarmonyPostfix] private static void Unequipped(Humanoid __instance, ItemData item) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (IsOurs(__instance, item)) { _holding = false; Leave((Player)__instance); } } [HarmonyPatch(typeof(Player), "OnDestroy")] [HarmonyPrefix] private static void PlayerGone(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { _holding = false; if (_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 (!IsAdmin()) { if (!_toldAdminOnly) { _toldAdminOnly = true; ((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 ((Object)(object)player != (Object)null && _holding && Keys.GameHasInput(player) && Keys.Down(Settings.CreativeKey)) { Settings.CreativeActive.Value = !Settings.CreativeActive.Value; if (Settings.CreativeActive.Value) { Enter(player); } else { Leave(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; } } public 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 struct State { public bool Visible; public int Mode; public int Planned; public string Reason; public bool Holding; public bool Admin; public bool Active; public int ConfigVersion; public int Language; } private const float LineSpacing = 4f; private const float PartSpacing = 6f; private static RectTransform _panel; private static RectTransform _root; private static GameObject _bar; private static Image _edge; private static int _alignedWidth; private static int _alignedHeight; 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>(); private static State _state; private static bool _hasState; private static bool _unfilled; private static int _language; private static bool _listening; [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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0226: 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_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) Rows.Clear(); _hasState = false; 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); Canvas componentInParent = buildHints.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { Log.Warning("The game's build hints have no canvas; key hints are off."); return; } _root = (RectTransform)((Component)componentInParent.rootCanvas).transform; _bar = buildHints; GameObject val8 = new GameObject("LetsBuild_KeyHints", new Type[1] { typeof(RectTransform) }); _panel = (RectTransform)val8.transform; ((Transform)_panel).SetParent((Transform)(object)_root, false); Vector3 lossyScale = buildHints.transform.lossyScale; Vector3 lossyScale2 = ((Transform)_root).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, 0.5f); _panel.anchorMax = new Vector2(1f, 0.5f); _panel.pivot = new Vector2(1f, 0.5f); _panel.anchoredPosition = Vector2.zero; Log.Info("Key hints line up with \"" + (((Object)(object)val6 != (Object)null) ? (((Object)val6).name + "/") : "") + ((Object)val7).name + "\"."); _edge = ((Component)val7).GetComponent<Image>(); _picture = _edge; VerticalLayoutGroup obj = val8.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)5; ((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; } if (Screen.width != _alignedWidth || Screen.height != _alignedHeight) { _alignedWidth = Screen.width; _alignedHeight = Screen.height; _picture = _edge; } AlignToPicture(); if (Changed()) { Collect(); _unfilled = true; } bool flag = Lines.Count > 0 && (Object)(object)_bar != (Object)null && _bar.activeInHierarchy; if (((Component)_panel).gameObject.activeSelf != flag) { ((Component)_panel).gameObject.SetActive(flag); } if (!flag || !_unfilled) { return; } _unfilled = false; 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_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: 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_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0206: 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_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0242: 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_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: 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); Vector3 val3 = ((Transform)((Graphic)picture).rectTransform).TransformPoint(new Vector3(num8, ((Rect)(ref rect)).center.y, 0f)); float x = ((Transform)_root).InverseTransformPoint(val3).x; rect2 = _root.rect; float num9 = Mathf.Min(0f, x - ((Rect)(ref rect2)).xMax); _panel.anchoredPosition = new Vector2(num9, 0f); 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 from the right "; 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 bool Changed() { if (!_listening) { _listening = true; Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, (Action)delegate { _language++; }); } Player localPlayer = Player.m_localPlayer; bool flag = Settings.ShowKeyHints.Value && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && ((Character)localPlayer).InPlaceMode() && !Hud.IsPieceSelectionVisible() && Keys.GameHasInput(localPlayer); int num = 0; if (flag) { Piece val = PlayerAccess.SelectedPiece(localPlayer); if ((Object)(object)val != (Object)null && PlantGrid.IsPlantPiece(val)) { num = ((Settings.PlantingEnabled.Value && !PlantGrid.Climbs(val)) ? 1 : 0); } else if (Settings.PrecisionEnabled.Value && PrecisionBuild.HoldsHammer(localPlayer)) { num = 2; } } State state = new State { Visible = flag, Mode = num, Planned = ((num == 1) ? PlantGrid.PlannedCount : 0), Reason = ((num == 1) ? PlantGrid.MainReason : null), Holding = CreativeMode.Holding, Admin = CreativeMode.IsAdmin(), Active = CreativeMode.Active, ConfigVersion = Settings.Version, Language = _language }; if (_hasState && state.Visible == _state.Visible && state.Mode == _state.Mode && state.Planned == _state.Planned && state.Reason == _state.Reason && state.Holding == _state.Holding && state.Admin == _state.Admin && state.Active == _state.Active && state.ConfigVersion == _state.ConfigVersion && state.Language == _state.Language) { return false; } _state = state; _hasState = true; 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 && !PlantGrid.Climbs(val)) { PlantLines(); } } else if (Settings.PrecisionEnabled.Value && PrecisionBuild.HoldsHammer(localPlayer)) { PrecisionLines(); } if (CreativeMode.Holding) { if (CreativeMode.IsAdmin()) { Add("$lb_creative: " + Texts.OnOff(CreativeMode.Active), Settings.CreativeKey); } 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 Func<Player, bool> PlayerTakesInput = TakeInputDelegate(); private static Func<Player, bool> TakeInputDelegate() { MethodInfo methodInfo = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); if (!(methodInfo != null)) { return null; } return AccessTools.MethodDelegate<Func<Player, bool>>(methodInfo, (object)null, true); } 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 PlayerTakesInput(player); } 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 Growth { private sealed class Spot { public bool Placed; public readonly List<Area> Areas = new List<Area>(1); public double PlantedAt = double.MinValue; public long NextPeriod; public double WetBefore; public long NowPeriod = long.MinValue; public bool NowWet; public int ForcedVersion = -1; public float RoofCheckedAt = float.NegativeInfinity; public bool Roofed; public int HiveVersion = -1; public int SettingsVersion = -1; public List<Component> Hives; } private sealed class Area { public BiomeSector Sector; public byte Edges; public bool Forced; public bool ForcedWet; } private readonly struct Period : IEquatable<Period> { private readonly BiomeSector _sector; private readonly byte _edges; private readonly long _index; public Period(BiomeSector sector, byte edges, long index) { _sector = sector; _edges = edges; _index = index; } public bool Equals(Period other) { if (_sector == other._sector && _edges == other._edges) { return _index == other._index; } return false; } public override bool Equals(object obj) { if (obj is Period other) { return Equals(other); } return false; } public override int GetHashCode() { int num = ((RuntimeHelpers.GetHashCode(_sector) * 397) ^ _edges) * 397; long index = _index; return num ^ index.GetHashCode(); } } private sealed class HiveState { public float CheckedAt = float.NegativeInfinity; public bool Working; } private const float Recheck = 10f; private const int MaxPeriods = 4096; private const int MaxForecast = 1000; private static readonly Func<EnvMan, List<EnvEntry>, EnvSetup> SelectEnvironment = AccessTools.MethodDelegate<Func<EnvMan, List<EnvEntry>, EnvSetup>>(AccessTools.Method(typeof(EnvMan), "SelectWeightedEnvironment", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Plant, float> GrowTime = AccessTools.MethodDelegate<Func<Plant, float>>(AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Beehive, bool> RightBiome = AccessTools.MethodDelegate<Func<Beehive, bool>>(AccessTools.Method(typeof(Beehive), "CheckBiome", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Beehive, bool> FreeSpace = AccessTools.MethodDelegate<Func<Beehive, bool>>(AccessTools.Method(typeof(Beehive), "HaveFreeSpace", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<Beehive, ZNetView> HiveView = AccessTools.FieldRefAccess<Beehive, ZNetView>("m_nview"); private static int _roofMask; private static readonly ConditionalWeakTable<Plant, Spot> Spots = new ConditionalWeakTable<Plant, Spot>(); private const float RainReach = 16f; private static readonly Vector2[] AreaSamples = BuildSamples(); private static readonly Dictionary<Period, bool> Weather = new Dictionary<Period, bool>(); private static EnvMan _weatherOf; private static string _forcedName = ""; private static bool _forcedWet; private static int _forcedVersion; private static bool _inRain; private static readonly List<Component> Hives = new List<Component>(); private static int _hiveVersion; private static readonly Predicate<Component> Gone = (Component hive) => (Object)(object)hive == (Object)null; private static MethodInfo _boxGroup; private static MethodInfo _boxQueens; private static MethodInfo _boxWarm; private static bool _toldBoxFailed; private static readonly ConditionalWeakTable<Component, HiveState> HiveStates = new ConditionalWeakTable<Component, HiveState>(); private static Vector2[] BuildSamples() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) List<Vector2> list = new List<Vector2> { Vector2.zero }; float[] array = new float[2] { 8f, 16f }; foreach (float num in array) { for (int j = 0; j < 8; j++) { float num2 = (float)j * (float)Math.PI / 4f; list.Add(new Vector2(Mathf.Cos(num2), Mathf.Sin(num2)) * num); } } return list.ToArray(); } private static void ReadForced(EnvMan env) { string text = env.m_debugEnv ?? ""; if (text == _forcedName) { return; } _forcedName = text; _forcedWet = false; foreach (EnvSetup environment in env.m_environments) { if (environment.m_name == text) { _forcedWet = environment.m_isWet; break; } } _forcedVersion++; } [HarmonyPatch(typeof(Plant), "TimeSincePlanted")] [HarmonyPostfix] private static void Rain(Plant __instance, ref double __result) { if (_inRain || !Settings.RainGrowth.Value || __result <= 0.0) { return; } _inRain = true; try { AddRain(__instance, ref __result); } finally { _inRain = false; } } private static void AddRain(Plant __instance, ref double __result) { float value = Settings.RainGrowthSpeed.Value; EnvMan instance = EnvMan.instance; if (value <= 1f || (Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } Spot orCreateValue = Spots.GetOrCreateValue(__instance); if (Place(__instance, orCreateValue)) { ReadForced(instance); double timeSeconds = ZNet.instance.GetTimeSeconds(); double num = WetSeconds(__instance, orCreateValue, instance, timeSeconds, timeSeconds - __result); if (num > 0.0 && !Roofed(__instance, orCreateValue)) { __result += num * (double)(value - 1f); } } } public static bool RainingOn(Plant plant) { EnvMan instance = EnvMan.instance; if (!Settings.RainGrowth.Value || Settings.RainGrowthSpeed.Value <= 1f || (Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || instance.m_environmentDuration <= 0 || !Spots.TryGetValue(plant, out var value)) { return false; } ReadForced(instance); long num = (long)ZNet.instance.GetTimeSeconds() / instance.m_environmentDuration; if (value.NowPeriod == num && value.ForcedVersion == _forcedVersion && value.NowWet) { return !value.Roofed; } return false; } public static double SecondsLeft(Plant plant, double since, double total) { double num = total - since; EnvMan instance = EnvMan.instance; float value = Settings.RainGrowthSpeed.Value; if (num <= 0.0 || !Settings.RainGrowth.Value || value <= 1f || (Object)(object)instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || instance.m_environmentDuration <= 0 || !Spots.TryGetValue(plant, out var value2) || !value2.Placed || Roofed(plant, value2)) { return Math.Max(0.0, num); } ReadForced(instance); long environmentDuration = instance.m_environmentDuration; double timeSeconds = ZNet.instance.GetTimeSeconds(); long num2 = (long)timeSeconds / environmentDuration; double num3 = 0.0; int num4 = 0; while (num4 < 1000) { double num5 = (double)(num2 + 1) * (double)environmentDuration - (timeSeconds + num3); double num6 = (Wet(instance, value2, num2) ? ((double)value) : 1.0); if (num <= num5 * num6) { return num3 + num / num6; } num -= num5 * num6; num3 += num5; num4++; num2++; } return num3 + num; } private static Area NewArea(BiomeSector sector, byte edges) { Area area = new Area { Sector = sector, Edges = edges }; foreach (AltBiome altBiome in sector.AltBiomes) { if (altBiome == null || string.IsNullOrEmpty(altBiome.m_forceEnvironment)) { continue; } area.Forced = true; foreach (EnvSetup environment in EnvMan.instance.m_environments) { if (environment.m_name == altBiome.m_forceEnvironment) { area.ForcedWet = environment.m_isWet; break; } } break; } return area; } private static bool Place(Plant plant, Spot spot) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0070: 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_007e: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (spot.Placed) { return true; } WorldGenerator instance = WorldGenerator.instance; AltBiomeWorldData val = ZNet.World?.m_biomeData; if (instance == null || (Object)(object)EnvMan.instance == (Object)null || val == null || !val.IsReady) { return false; } Vector3 position = ((Component)plant).transform.position; spot.Areas.Clear(); Vector2[] areaSamples = AreaSamples; Vector3 val3 = default(Vector3); foreach (Vector2 val2 in areaSamples) { ((Vector3)(ref val3))..ctor(position.x + val2.x, position.y, position.z + val2.y); BiomeSector biomeSector = instance.GetBiomeSector(val3, false); byte b = (byte)((WorldGenerator.IsAshlands(val3.x, val3.z) ? 1u : 0u) | (uint)(WorldGenerator.IsDeepnorth(val3.x, val3.y) ? 2 : 0)); bool flag = false; foreach (Area area in spot.Areas) { if (area.Sector == biomeSector && area.Edges == b) { flag = true; break; } } if (!flag) { spot.Areas.Add(NewArea(biomeSector, b)); } } spot.Placed = true; return true; } private static double WetSeconds(Plant plant, Spot spot, EnvMan env, double now, double plantedAt) { long environmentDuration = env.m_environmentDuration; if (environmentDuration <= 0 || plantedAt < 0.0) { return 0.0; } long num = (long)now / environmentDuration; if (Math.Abs(plantedAt - spot.PlantedAt) > 1.0 || num < spot.NextPeriod || spot.ForcedVersion != _forcedVersion) { spot.ForcedVersion = _forcedVersion; spot.PlantedAt = plantedAt; spot.NextPeriod = (long)plantedAt / environmentDuration; spot.WetBefore = 0.0; spot.NowPeriod = long.MinValue; } if (spot.NextPeriod < num) { double num2 = plantedAt + (double)GrowTime(plant); long num3 = Math.Min(num, (long)num2 / environmentDuration + 1); while (spot.NextPeriod < num3) { long nextPeriod = spot.NextPeriod; if (Wet(env, spot, nextPeriod)) { spot.WetBefore += (double)(nextPeriod + 1) * (double)environmentDuration - Math.Max((double)nextPeriod * (double)environmentDuration, plantedAt); } spot.NextPeriod++; } } double num4 = spot.WetBefore; if (spot.NextPeriod == num) { if (spot.NowPeriod != num) { spot.NowPeriod = num; spot.NowWet = Wet(env, spot, num); } if (spot.NowWet) { num4 += now - Math.Max((double)num * (double)environmentDuration, plantedAt); } } return num4; } private static bool Wet(EnvMan env, Spot spot, long period) { if (_forcedName.Length > 0) { return _forcedWet; } foreach (Area area in spot.Areas) { if (Wet(env, area, period)) { return true; } } return false; } private static bool Wet(EnvMan env, Area area, long period) { if (area.Forced) { return area.ForcedWet; } if (env != _weatherOf || Weather.Count > 4096) { Weather.Clear(); _weatherOf = env; } Period key = new Period(area.Sector, area.Edges, period); if (!Weather.TryGetValue(key, out var value)) { value = Choose(env, area, period)?.m_isWet ?? false; Weather[key] = value; } return value; } private static EnvSetup Choose(EnvMan env, Area area, long period) { //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_0096: Unknown result type (might be due to invalid IL or missing references) State state = Random.state; Random.InitState((int)period); EnvSetup result = null; List<EnvEntry> availableEnvironments = env.GetAvailableEnvironments(area.Sector); if (availableEnvironments != null && availableEnvironments.Count > 0) { result = SelectEnvironment(env, availableEnvironments); foreach (EnvEntry item in availableEnvironments) { if (item.m_ashlandsOverride && (area.Edges & 1) != 0) { result = item.m_env; } if (item.m_deepnorthOverride && (area.Edges & 2) != 0) { result = item.m_env; } } } Random.state = state; return result; } private static bool Roofed(Plant plant, Spot spot) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (time - spot.RoofCheckedAt >= 10f) { spot.RoofCheckedAt = time; if (_roofMask == 0) { _roofMask = LayerMask.GetMask(new string[3] { "Default", "static_solid", "piece" }); } spot.Roofed = Physics.Raycast(((Component)plant).transform.position, Vector3.up, 100f, _roofMask); } return spot.Roofed; } [HarmonyPatch(typeof(Beehive), "Awake")] [HarmonyPostfix] private static void HiveBuilt(Beehive __instance) { ZNetView val = HiveView.Invoke(__instance); if ((Object)(object)val != (Object)null && val.GetZDO() != null) { Hives.Add((Component)(object)__instance); _hiveVersion++; } } public static void PatchBeeBoxes(Harmony harmony) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown Type type = AccessTools.TypeByName("BetrValheim.Bees.BeeBox"); if (!(type == null)) { MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); _boxGroup = AccessTools.Method(type, "Group", (Type[])null, (Type[])null); _boxQueens = AccessTools.Method(type, "Queens", (Type[])null, (Type[])null); _boxWarm = AccessTools.Method(type, "Warm", (Type[])null, (Type[])null); if (methodInfo == null || _boxGroup == null || _boxQueens == null || _boxWarm == null) { _boxGroup = (_boxQueens = (_boxWarm = null)); Log.Warning("BetrValheim's bee boxes could not be read; they do not speed up growth."); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Growth), "BoxBuilt", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void BoxBuilt(MonoBehaviour __instance) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.GetZDO() != null) { Hives.Add((Component)(object)__instance); _hiveVersion++; } } [HarmonyPatch(typeof(Plant), "GetGrowTime")] [HarmonyPostfix] private static void Bees(Plant __instance, ref float __result) { if (BeesAt(__instance)) { __result /= Settings.BeeGrowthSpeed.Value; } } public static bool BeesAt(Plant plant) { if (!Settings.BeeGrowth.Value || Settings.BeeGrowthSpeed.Value <= 1f || Hives.Count == 0) { return false; } Spot orCreateValue = Spots.GetOrCreateValue(plant); if (orCreateValue.HiveVersion != _hiveVersion || orCreateValue.SettingsVersion != Settings.Version) { FindHives(plant, orCreateValue); } List<Component> hives = orCreateValue.Hives; if (hives == null) { return false; } for (int i = 0; i < hives.Count; i++) { Component val = hives[i]; if ((Object)(object)val == (Object)null) { _hiveVersion++; } else if (Working(val)) { return true; } } return false; } private static void FindHives(Plant plant, Spot spot) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_006e: Unknown result type (might be due to invalid IL or missing references) if (Hives.RemoveAll(Gone) > 0) { _hiveVersion++; } spot.Hives?.Clear(); float value = Settings.BeeRange.Value; float num = value * value; Vector3 position = ((Component)plant).transform.position; foreach (Component hive in Hives) { Vector3 val = hive.transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= num) { (spot.Hives ?? (spot.Hives = new List<Component>(1))).Add(hive); } } spot.HiveVersion = _hiveVersion; spot.SettingsVersion = Settings.Version; } private static bool Working(Component hive) { HiveState orCreateValue = HiveStates.GetOrCreateValue(hive); float time = Time.time; if (time - orCreateValue.CheckedAt >= 10f) { orCreateValue.CheckedAt = time; Beehive val = (Beehive)(object)((hive is Beehive) ? hive : null); orCreateValue.Working = ((val == null) ? BoxWorking(hive) : (RightBiome(val) && FreeSpace(val))); } return orCreateValue.Working; } private static bool BoxWorking(Component box) { if (_boxGroup == null) { return false; } try { object obj = _boxGroup.Invoke(box, null); return (int)_boxQueens.Invoke(null, new object[1] { obj }) > 0 && (bool)_boxWarm.Invoke(box, null); } catch (Exception ex) { if (!_toldBoxFailed) { _toldBoxFailed = true; Log.Warning("BetrValheim's bee box could not be asked whether its bees work: " + (ex.InnerException ?? ex).Message); } return false; } } } [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()) { return; } double num = (double)SincePlanted.Invoke(__instance, null); float num2 = (float)GrowTime.Invoke(__instance, null); if (!(num2 <= 0f)) { double num3 = Growth.SecondsLeft(__instance, num, num2); 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>"; string text2 = ((num3 > 0.0) ? Boost(__instance) : null); if (text2 != null) { __result = __result + "\n<color=#a8d8a0>" + text2 + "</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 Boost(Plant plant) { bool flag = Growth.RainingOn(plant); bool flag2 = Growth.BeesAt(plant); if (!flag && !flag2) { return null; } float num = (flag ? Settings.RainGrowthSpeed.Value : 1f); float num2 = (flag2 ? Settings.BeeGrowthSpeed.Value : 1f); string text = Texts.T("$lb_growth") + " ×" + Texts.Number(num * num2) + " ("; text = ((!(flag && flag2)) ? (text + Texts.T(flag ? "$lb_rain" : "$lb_bees")) : (text + Texts.T("$lb_rain") + " ×" + Texts.Number(num) + ", " + Texts.T("$lb_bees") + " ×" + Texts.Number(num2))); return text + ")"; } 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; private static readonly object Yes = new object(); private static readonly object No = new object(); private static readonly ConditionalWeakTable<Pickable, object> Growing = new ConditionalWeakTable<Pickable, object>(); public static void Tick(Player player) { if ((Object)(object)player != (Object)null && Keys.Down(Settings.ReplantKey) && Keys.GameHasInput(player)) { 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) { if (Growing.TryGetValue(pickable, out var value)) { return value == Yes; } string prefabName = Utils.GetPrefabName(((Component)pickable).gameObject); bool flag = SeedMap().ContainsKey(prefabName) || Plantables.IsWildPlant(prefabName); if ((Object)(object)ObjectDB.instance != (Object)null) { Growing.Add(pickable, flag ? Yes : No); } return flag; } 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; } } internal static class MeshCut { private sealed class Builder { private readonly Vector3[] _v; private readonly Vector3[] _n; private readonly Vector4[] _t; private readonly Color[] _c; private readonly Vector2[] _uv; private readonly Vector2[] _uv2; public readonly List<Vector3> V = new List<Vector3>(); public readonly List<Vector3> N = new List<Vector3>(); public readonly List<Vector4> T = new List<Vector4>(); public readonly List<Color> C = new List<Color>(); public readonly List<Vector2> UV = new List<Vector2>(); public readonly List<Vector2> UV2 = new List<Vector2>(); private readonly Dictionary<int, int> _kept = new Dictionary<int, int>(); private readonly Dictionary<long, int> _cuts = new Dictionary<long, int>(); public bool HasN => _n.Length == _v.Length; public bool HasT => _t.Length == _v.Length; public bool HasC => _c.Length == _v.Length; public bool HasUV => _uv.Length == _v.Length; public bool HasUV2 => _uv2.Length == _v.Length; public Builder(Mesh mesh) { _v = mesh.vertices; _n = mesh.normals; _t = mesh.tangents; _c = mesh.colors; _uv = mesh.uv; _uv2 = mesh.uv2; } public float Y(int i) { return _v[i].y; } public int Keep(int i) { //IL_001b: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!_kept.TryGetValue(i, out var value)) { value = Add(_v[i], HasN ? _n[i] : Vector3.up, HasT ? _t[i] : Vector4.zero, HasC ? _c[i] : Color.white, HasUV ? _uv[i] : Vector2.zero, HasUV2 ? _uv2[i] : Vector2.zero); _kept[i] = value; } return value; } public int Cut(int a, int b, float cut) { //IL_005b: 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_006d: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) long key = ((a < b) ? (((long)a << 32) | (uint)b) : (((long)b << 32) | (uint)a)); if (!_cuts.TryGetValue(key, out var value)) { float num = Mathf.InverseLerp(_v[a].y, _v[b].y, cut); Vector3 v = Vector3.Lerp(_v[a], _v[b], num); Vector3 n; if (!HasN) { n = Vector3.up; } else { Vector3 val = Vector3.Lerp(_n[a], _n[b], num); n = ((Vector3)(ref val)).normalized; } value = Add(v, n, HasT ? Vector4.Lerp(_t[a], _t[b], num) : Vector4.zero, HasC ? Color.Lerp(_c[a], _c[b], num) : Color.white, HasUV ? Vector2.Lerp(_uv[a], _uv[b], num) : Vector2.zero, HasUV2 ? Vector2.Lerp(_uv2[a], _uv2[b], num) : Vector2.zero); _cuts[key] = value; } return value; } public int Add(Vector3 v, Vector3 n, Vector4 t, Color c, Vector2 uv, Vector2 uv2) { //IL_0006: 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_001e: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) V.Add(v); N.Add(n); T.Add(t); C.Add(c); UV.Add(uv); UV2.Add(uv2); return V.Count - 1; } public int Lid(int i) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) return Add(V[i], Vector3.up, T[i], C[i], UV[i], UV2[i]); } } public static Mesh Below(Mesh source, float cut) { //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown Builder builder = new Builder(source); int subMeshCount = source.subMeshCount; List<int>[] array = new List<int>[subMeshCount]; List<int> list = new List<int>(4); for (int i = 0; i < subMeshCo