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 LoadBearing v1.1.0
plugins/LoadBearing.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LoadBearing")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LoadBearing")] [assembly: AssemblyTitle("LoadBearing")] [assembly: AssemblyVersion("1.0.0.0")] namespace LoadBearing; [BepInPlugin("anwo.LoadBearing", "LoadBearing", "1.1.0")] public class LoadBearingPlugin : BaseUnityPlugin { private struct Pending { public WearNTear Piece; public float Value; public float Distance; } public const string Guid = "anwo.LoadBearing"; public const string Name = "LoadBearing"; public const string Version = "1.1.0"; internal static ConfigEntry<KeyboardShortcut> ToggleKey; internal static ConfigEntry<bool> OnAtStart; internal static ConfigEntry<bool> BuildModeOnly; internal static ConfigEntry<bool> ShowMessages; internal static ConfigEntry<float> Radius; internal static ConfigEntry<float> ShowBelow; internal static ConfigEntry<bool> ShowGrounded; internal static ConfigEntry<int> PiecesPerFrame; internal static ConfigEntry<float> RescanSeconds; internal static ConfigEntry<bool> MoveBuildingPieces; internal static ConfigEntry<bool> AreaRepairOn; internal static ConfigEntry<float> AreaRepairRadius; internal static ConfigEntry<KeyCode> AreaRepairKey; internal static readonly HashSet<WearNTear> Lit = new HashSet<WearNTear>(); internal static bool Active; private static FieldRef<WearNTear, ZNetView> _nview; private static Func<WearNTear, float> _supportColorValue; private static Action<WearNTear> _resetHighlight; private static Func<Humanoid, ItemData> _getRightItem; private bool _enabled; private Harmony _harmony; private readonly List<Pending> _queue = new List<Pending>(); private readonly HashSet<WearNTear> _wanted = new HashSet<WearNTear>(); private readonly List<WearNTear> _drop = new List<WearNTear>(); private readonly Dictionary<WearNTear, float> _shown = new Dictionary<WearNTear, float>(); private int _queueIndex; private float _nextScan; private float _nextFull; private const float FullRefreshSeconds = 10f; private static readonly Comparison<Pending> ByDistance = (Pending a, Pending b) => a.Distance.CompareTo(b.Distance); private void Awake() { //IL_001a: 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_00c6: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Expected O, but got Unknown //IL_033a: Unknown result type (might be due to invalid IL or missing references) ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "Toggle key", new KeyboardShortcut((KeyCode)277, Array.Empty<KeyCode>()), "Turns the support view on or off."); OnAtStart = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "On at start", false, "Whether the support view starts switched on when you load the game. Off by default: press the toggle key to turn it on."); BuildModeOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Build mode only", true, "Only colour pieces while the hammer is out in build mode. Turn off to see support any time the view is switched on."); ShowMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Show on/off message", true, "Show a short message in the top-left corner when you switch the view on or off."); Radius = ((BaseUnityPlugin)this).Config.Bind<float>("2 - View", "Radius", 30f, new ConfigDescription("How far around you pieces are coloured, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>())); ShowBelow = ((BaseUnityPlugin)this).Config.Bind<float>("2 - View", "Only pieces weaker than", 1f, new ConfigDescription("1 colours every piece. Lower it to colour only weak pieces: 0.5 = pieces at half support or less, 0.25 = only pieces close to collapsing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); ShowGrounded = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - View", "Show grounded pieces", true, "Colour pieces that rest directly on the ground (blue). Turn off to see only pieces held up by other pieces."); PiecesPerFrame = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Performance", "Pieces per frame", 150, new ConfigDescription("How many pieces are recoloured each frame. Lower it if big bases stutter while the view is on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 2000), Array.Empty<object>())); RescanSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Performance", "Refresh interval", 1f, new ConfigDescription("Seconds between checks for pieces whose support changed. Only pieces that changed are recoloured, so a lower value costs little, but checking still goes through every piece in range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>())); MoveBuildingPieces = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Moving", "Move building pieces", true, "With ZenRedecorate, walls, floors, beams and other building pieces can be moved too, not only furniture. Pieces resting on a moved piece check their support again, and fall if nothing else holds them up."); AreaRepairOn = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Repairing", "Area repair", true, "With the hammer's repair tool selected, hold the Area repair key (Shift) while you click: every damaged building piece within Area repair radius of the piece you aim at (or of you, if you aim at nothing) is repaired at once, instead of only the one piece. The game's own rules still count for each piece: its crafting station has to be near it (the workbench for wood, the stonecutter for stone and so on), and pieces in a ward you have no access to are skipped. The message says how many were repaired and why any were left. One click costs the stamina and hammer wear of a single repair. Off: holding the key changes nothing and the hammer repairs one piece as usual."); AreaRepairRadius = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Repairing", "Area repair radius", 10f, new ConfigDescription("How far around the piece you aim at (or around you) Area repair reaches, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>())); AreaRepairKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("5 - Repairing", "Area repair key", (KeyCode)304, "The key to hold while you click with the repair tool to repair the whole area. With Left Shift, Right Shift works too."); _enabled = OnAtStart.Value; _nview = AccessTools.FieldRefAccess<WearNTear, ZNetView>("m_nview"); _supportColorValue = AccessTools.MethodDelegate<Func<WearNTear, float>>(AccessTools.Method(typeof(WearNTear), "GetSupportColorValue", (Type[])null, (Type[])null), (object)null, true); _resetHighlight = AccessTools.MethodDelegate<Action<WearNTear>>(AccessTools.Method(typeof(WearNTear), "ResetHighlight", (Type[])null, (Type[])null), (object)null, true); _getRightItem = AccessTools.MethodDelegate<Func<Humanoid, ItemData>>(AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null), (object)null, true); ((BaseUnityPlugin)this).Config.Save(); _harmony = new Harmony("anwo.LoadBearing"); _harmony.PatchAll(typeof(ResetHighlightPatch)); _harmony.PatchAll(typeof(AreaRepair)); ZenMoving.Log = ((BaseUnityPlugin)this).Logger; ZenMoving.TryPatch(_harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Toggle key: {2}", "LoadBearing", "1.1.0", ToggleKey.Value)); } private void OnDestroy() { ClearAll(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && !IsTyping()) { KeyboardShortcut value = ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _enabled = !_enabled; if (ShowMessages.Value) { ((Character)localPlayer).Message((MessageType)1, _enabled ? "Support view on: blue = on the ground, green = strong, red = about to fall" : "Support view off", 0, (Sprite)null, false); } } } if (!_enabled || !((Object)(object)localPlayer != (Object)null) || ((Character)localPlayer).IsDead() || (BuildModeOnly.Value && !InBuildMode(localPlayer))) { if (Active) { ClearAll(); } return; } Active = true; if (Time.time >= _nextScan) { _nextScan = Time.time + RescanSeconds.Value; Scan(((Component)localPlayer).transform.position); } int value2 = PiecesPerFrame.Value; while (value2-- > 0 && _queueIndex < _queue.Count) { Pending pending = _queue[_queueIndex++]; WearNTear piece = pending.Piece; if (!((Object)(object)piece == (Object)null)) { try { piece.Highlight(); Lit.Add(piece); _shown[piece] = pending.Value; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Highlight failed on " + ((Object)piece).name + ": " + ex.Message)); } } } } private void Scan(Vector3 center) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //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) _wanted.Clear(); _queue.Clear(); _queueIndex = 0; bool flag = Time.time >= _nextFull; if (flag) { _nextFull = Time.time + 10f; } float value = Radius.Value; float num = value * value; float value2 = ShowBelow.Value; bool value3 = ShowGrounded.Value; List<WearNTear> allInstances = WearNTear.GetAllInstances(); for (int i = 0; i < allInstances.Count; i++) { WearNTear val = allInstances[i]; if ((Object)(object)val == (Object)null) { continue; } Vector3 val2 = ((Component)val).transform.position - center; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude > num) { continue; } ZNetView val3 = _nview.Invoke(val); if ((Object)(object)val3 == (Object)null || !val3.IsValid()) { continue; } float num2; try { num2 = _supportColorValue(val); } catch { continue; } if ((num2 < 0f) ? value3 : (num2 <= value2)) { _wanted.Add(val); if (flag || !_shown.TryGetValue(val, out var value4) || !Same(value4, num2)) { _queue.Add(new Pending { Piece = val, Value = num2, Distance = sqrMagnitude }); } } } if (_queue.Count > 1) { _queue.Sort(ByDistance); } _drop.Clear(); foreach (WearNTear item in Lit) { if ((Object)(object)item == (Object)null || !_wanted.Contains(item)) { _drop.Add(item); } } foreach (WearNTear item2 in _drop) { Lit.Remove(item2); _shown.Remove(item2); Reset(item2); } } internal static bool Same(float a, float b) { if (a < 0f || b < 0f) { if (a < 0f) { return b < 0f; } return false; } return Mathf.Abs(a - b) < 0.01f; } private void ClearAll() { Active = false; _queue.Clear(); _queueIndex = 0; _wanted.Clear(); _shown.Clear(); _nextFull = 0f; if (Lit.Count == 0) { return; } List<WearNTear> list = new List<WearNTear>(Lit); Lit.Clear(); foreach (WearNTear item in list) { Reset(item); } } private void Reset(WearNTear piece) { if ((Object)(object)piece == (Object)null) { return; } try { ((MonoBehaviour)piece).CancelInvoke("ResetHighlight"); _resetHighlight(piece); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Reset failed on " + ((Object)piece).name + ": " + ex.Message)); } } private static bool InBuildMode(Player player) { if (!((Character)player).InPlaceMode()) { return false; } PieceTable val = _getRightItem((Humanoid)(object)player)?.m_shared?.m_buildPieces; if ((Object)(object)val == (Object)null) { return true; } string text = ((Object)val).name ?? ""; if (text.IndexOf("Hoe", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("Cultivator", StringComparison.OrdinalIgnoreCase) < 0; } return false; } private static bool IsTyping() { if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.InTextInput()) { return true; } Chat instance = Chat.instance; if ((Object)(object)instance != (Object)null) { return instance.HasFocus(); } return false; } } [HarmonyPatch(typeof(WearNTear), "ResetHighlight")] internal static class ResetHighlightPatch { private static bool Prefix(WearNTear __instance) { if (LoadBearingPlugin.Active) { return !LoadBearingPlugin.Lit.Contains(__instance); } return true; } } internal static class ZenMoving { private static Action<WearNTear> s_clearSupport; private static readonly FieldRef<WearNTear, ZNetView> s_nview = AccessTools.FieldRefAccess<WearNTear, ZNetView>("m_nview"); private const PieceCategory NotChanged = (PieceCategory)(-1); private static float s_warned; internal static ManualLogSource Log; internal static void TryPatch(Harmony harmony) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00c2: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0100: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown ManualLogSource val = Log ?? Logger.CreateLogSource("LoadBearing"); try { Type type = AccessTools.TypeByName("ZenRedecorate.Redecorate"); if (type == null) { val.LogInfo((object)"ZenRedecorate not installed: moving building pieces is not available."); return; } MethodInfo methodInfo = AccessTools.Method(type, "CanMove", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "UpdateOrientation", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type, "PickupPiece", (Type[])null, (Type[])null); s_clearSupport = AccessTools.MethodDelegate<Action<WearNTear>>(AccessTools.Method(typeof(WearNTear), "ClearCachedSupport", (Type[])null, (Type[])null), (object)null, true); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ZenMoving), "CanMovePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ZenMoving), "CanMoveFinalizer", (Type[])null), (HarmonyMethod)null); } if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(ZenMoving), "OrientPrefix", (Type[])null), new HarmonyMethod(typeof(ZenMoving), "OrientPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(ZenMoving), "PickupPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } val.LogInfo((object)"ZenRedecorate found: building pieces can be moved (setting '4 - Moving')."); } catch (Exception ex) { val.LogWarning((object)("Hooking into ZenRedecorate failed, building pieces stay unmovable: " + ex.Message)); } } internal static bool IsBuilding(Piece piece) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((Object)(object)piece == (Object)null || (int)piece.m_category == 4) { return false; } if ((int)piece.m_category == 2 || (int)piece.m_category == 3) { return true; } WearNTear component = ((Component)piece).GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { return component.m_supports; } return false; } private static void CanMovePrefix(Piece __0, out PieceCategory __state) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected I4, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) __state = (PieceCategory)(-1); try { if (LoadBearingPlugin.MoveBuildingPieces.Value && IsBuilding(__0)) { __state = (PieceCategory)(int)__0.m_category; __0.m_category = (PieceCategory)4; } } catch { } } private static Exception CanMoveFinalizer(Exception __exception, Piece __0, PieceCategory __state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((int)__state != -1 && (Object)(object)__0 != (Object)null) { __0.m_category = __state; } return __exception; } private static void OrientPrefix(GameObject __0, out Vector3 __state) { //IL_0017: 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_001c: Unknown result type (might be due to invalid IL or missing references) __state = (((Object)(object)__0 != (Object)null) ? __0.transform.position : Vector3.zero); } private static void OrientPostfix(GameObject __0, Vector3 __state) { //IL_007d: 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_0050: 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_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) try { if ((Object)(object)__0 == (Object)null || s_clearSupport == null || (Object)(object)__0.GetComponent<WearNTear>() == (Object)null) { return; } float num = 4f; Collider[] componentsInChildren = __0.GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && !val.isTrigger) { float num2 = num; Bounds bounds = val.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; num = Mathf.Max(num2, ((Vector3)(ref extents)).magnitude + 2f); } } Refresh(__state, num); Refresh(__0.transform.position, num); } catch (Exception ex) { Debug.LogWarning((object)("[LoadBearing] Refreshing support after a move failed: " + ex.Message)); } } private static void Refresh(Vector3 at, float reach) { //IL_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) float num = reach * reach; foreach (WearNTear allInstance in WearNTear.GetAllInstances()) { if ((Object)(object)allInstance == (Object)null) { continue; } Vector3 val = ((Component)allInstance).transform.position - at; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { ZNetView val2 = s_nview.Invoke(allInstance); if (!((Object)(object)val2 == (Object)null) && val2.IsValid() && val2.IsOwner()) { s_clearSupport(allInstance); } } } } private static void PickupPostfix(Piece __0) { try { if (LoadBearingPlugin.MoveBuildingPieces.Value && IsBuilding(__0) && !(Time.time - s_warned < 20f)) { s_warned = Time.time; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Moving a building piece: anything resting on it may fall", 0, (Sprite)null, false); } } } catch { } } } [HarmonyPatch] internal static class AreaRepair { private static readonly FieldRef<Player, bool> s_noPlacementCost = AccessTools.FieldRefAccess<Player, bool>("m_noPlacementCost"); private static readonly FieldRef<Character, ZSyncAnimation> s_zanim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim"); private static readonly MethodInfo s_buildStamina = AccessTools.Method(typeof(Player), "GetBuildStamina", (Type[])null, (Type[])null); private static readonly List<Piece> s_pieces = new List<Piece>(); private const int MostEffects = 8; internal static bool Held() { //IL_000a: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 ConfigEntry<KeyCode> areaRepairKey = LoadBearingPlugin.AreaRepairKey; if (areaRepairKey == null || (int)areaRepairKey.Value == 0) { return false; } if (Input.GetKey(areaRepairKey.Value)) { return true; } if ((int)areaRepairKey.Value == 304) { return Input.GetKey((KeyCode)303); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "Repair")] private static bool Prefix(Player __instance, ItemData toolItem) { //IL_0062: 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_00f1: 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_0147: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) try { if (LoadBearingPlugin.AreaRepairOn == null || !LoadBearingPlugin.AreaRepairOn.Value) { return true; } if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).InPlaceMode() || !Held()) { return true; } Piece hoveringPiece = __instance.GetHoveringPiece(); Vector3 val = (((Object)(object)hoveringPiece != (Object)null) ? ((Component)hoveringPiece).transform.position : ((Component)__instance).transform.position); s_pieces.Clear(); Piece.GetAllPiecesInRadius(val, LoadBearingPlugin.AreaRepairRadius.Value, s_pieces); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; bool flag = s_noPlacementCost.Invoke(__instance); foreach (Piece s_piece in s_pieces) { if ((Object)(object)s_piece == (Object)null) { continue; } WearNTear component = ((Component)s_piece).GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null || component.GetHealthPercentage() >= 0.999f) { continue; } Vector3 position = ((Component)s_piece).transform.position; if (!flag && (Object)(object)s_piece.m_craftingStation != (Object)null && (Object)(object)CraftingStation.HaveBuildStationInRange(s_piece.m_craftingStation.m_name, position) == (Object)null && (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGlobalKey((GlobalKeys)27))) { num2++; } else if (!PrivateArea.CheckAccess(position, 0f, false, false)) { num3++; } else if (component.Repair()) { num++; if (num4 < 8 && s_piece.m_placeEffect != null) { s_piece.m_placeEffect.Create(position, ((Component)s_piece).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); num4++; } } } s_pieces.Clear(); if (num > 0) { __instance.FaceLookDirection(); ZSyncAnimation val2 = s_zanim.Invoke((Character)(object)__instance); if ((Object)(object)val2 != (Object)null && toolItem != null) { val2.SetTrigger(toolItem.m_shared.m_attack.m_attackAnimation); } if (s_buildStamina != null) { ((Character)__instance).UseStamina((float)s_buildStamina.Invoke(__instance, null)); } if (toolItem != null) { ((Character)__instance).UseEitr(toolItem.m_shared.m_attack.m_attackEitr); if (toolItem.m_shared.m_useDurability) { toolItem.m_durability = Math.Max(0f, toolItem.m_durability - toolItem.m_shared.m_useDurabilityDrain * Game.m_durabilityRate); } } } ((Character)__instance).Message((MessageType)1, Words(num, num2, num3), 0, (Sprite)null, false); return false; } catch (Exception ex) { Logger.CreateLogSource("LoadBearing").LogWarning((object)("Area repair failed, repairing one piece instead: " + ex.Message)); return true; } } internal static string Words(int repaired, int noStation, int warded) { string text = ((repaired == 0) ? "Nothing around here needs repair" : ("Repaired " + repaired + ((repaired == 1) ? " piece" : " pieces"))); List<string> list = new List<string>(); if (noStation > 0) { list.Add(noStation + ((noStation == 1) ? " needs its" : " need their") + " crafting station nearby"); } if (warded > 0) { list.Add(warded + ((warded == 1) ? " is" : " are") + " in a ward you can't use"); } if (list.Count > 0) { text = ((repaired == 0) ? "Nothing repaired: " : (text + "; ")) + string.Join(", ", list.ToArray()); } return text; } }