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 HammerHotkeys v1.0.0
HammerHotkeys.dll
Decompiled 5 days 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 UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("HammerHotkeys")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HammerHotkeys")] [assembly: AssemblyTitle("HammerHotkeys")] [assembly: AssemblyVersion("1.0.0.0")] namespace HammerHotkeys; [BepInPlugin("DMT.HammerHotkeys", "HammerHotkeys", "1.0.0")] public class HammerHotkeysPlugin : BaseUnityPlugin { private struct Bind { public KeyCode Key; public string Piece; } internal const string PluginGUID = "DMT.HammerHotkeys"; internal const string PluginName = "HammerHotkeys"; internal const string PluginVersion = "1.0.0"; private const int MaxPendingAttempts = 30; private static ConfigEntry<string> BindsEntry; private static ConfigEntry<bool> AutoEquipEntry; private static ConfigEntry<bool> RequireAvailableEntry; private static ConfigEntry<bool> PlaySoundEntry; private static ConfigEntry<bool> ShowMessagesEntry; private static ConfigEntry<bool> OpenMenuEntry; private readonly List<Bind> _binds = new List<Bind>(); private readonly HashSet<string> _warnedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private Piece _pending; private int _pendingAttempts; private void Awake() { BindsEntry = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Binds", "F6=Workbench;F7=Portal;F8=Stonecutter", "Key=Piece pairs separated by ';'. The piece name is matched against the prefab name, the $piece_... localization key, and the English display name."); AutoEquipEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Auto Equip Hammer", true, "Equip the tool that contains the piece automatically if it is not already held."); RequireAvailableEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Require Available", true, "Only select pieces that are currently available/unlocked (same rule as the vanilla build menu)."); PlaySoundEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Play Sound", true, "Play the vanilla selection sound when a piece is selected."); ShowMessagesEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Show Messages", true, "Show a center screen message when a bind fires or fails."); OpenMenuEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Open Build Menu On Select", false, "Open the build menu after selecting the piece instead of keeping it closed."); ParseBinds(); BindsEntry.SettingChanged += OnBindsSettingChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded with {2} bind(s)", "HammerHotkeys", "1.0.0", _binds.Count)); } private void OnBindsSettingChanged(object sender, EventArgs e) { ParseBinds(); } private void ParseBinds() { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) _binds.Clear(); string[] array = (BindsEntry.Value ?? string.Empty).Split(new char[1] { ';' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf('='); if (num <= 0 || num >= text.Length - 1) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Invalid bind '" + text + "', expected format Key=Piece")); continue; } string text2 = text.Substring(0, num).Trim(); string piece = text.Substring(num + 1).Trim(); if (!Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Invalid key '" + text2 + "' in bind '" + text + "'")); } else { _binds.Add(new Bind { Key = result, Piece = piece }); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {_binds.Count} bind(s): {DescribeBinds()}"); } private string DescribeBinds() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (_binds.Count == 0) { return "none"; } List<string> list = new List<string>(_binds.Count); foreach (Bind bind in _binds) { list.Add($"{bind.Key}={bind.Piece}"); } return string.Join(", ", list); } private void Update() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || IsBlocked(localPlayer)) { return; } if ((Object)(object)_pending != (Object)null) { AttemptPending(localPlayer); } if (_binds.Count == 0) { return; } foreach (Bind bind in _binds) { if (Input.GetKeyDown(bind.Key)) { HandleBind(localPlayer, bind); break; } } } private static bool IsBlocked(Player player) { if (!((Character)player).IsDead() && !Console.IsVisible() && !TextInput.IsVisible() && !InventoryGui.IsVisible()) { return Menu.IsVisible(); } return true; } private void HandleBind(Player player, Bind bind) { if (!TryResolve(player, bind.Piece, out var tool, out var piece)) { WarnUnknownPiece(player, bind.Piece); return; } if (((Humanoid)player).RightItem != tool) { if (!AutoEquipEntry.Value) { ShowMessage(player, "Hold " + DescribeTool(tool) + " first"); return; } if (!((Humanoid)player).EquipItem(tool, true)) { ShowMessage(player, "Can't equip " + DescribeTool(tool)); return; } } if (RequireAvailableEntry.Value && !player.IsPieceAvailable(piece)) { ShowMessage(player, DescribePiece(piece) + " is not available yet"); return; } _pending = piece; _pendingAttempts = 30; AttemptPending(player); } private void AttemptPending(Player player) { Piece pending = _pending; if (!((Object)(object)pending == (Object)null)) { if (player.SetSelectedPiece(pending) || (Object)(object)player.GetSelectedPiece() == (Object)(object)pending) { _pending = null; OnSelected(player, pending); } else if (--_pendingAttempts <= 0) { _pending = null; ShowMessage(player, "Couldn't select " + DescribePiece(pending)); ((BaseUnityPlugin)this).Logger.LogWarning((object)("SetSelectedPiece failed for '" + ((Object)pending).name + "' (place mode not ready?)")); } } } private void OnSelected(Player player, Piece piece) { Hud instance = Hud.instance; BuildUi val = (((Object)(object)instance != (Object)null) ? instance.m_buildUi : null); bool flag = (Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy; if (OpenMenuEntry.Value) { if ((Object)(object)val != (Object)null && !flag) { val.OpenBuildMenu(); } } else if (flag) { val.Close(); } if (PlaySoundEntry.Value) { player.PlayButtonSound(); } ShowMessage(player, DescribePiece(piece) + " ready"); } private void ShowMessage(Player player, string text) { if (ShowMessagesEntry.Value) { ((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false); } } private void WarnUnknownPiece(Player player, string name) { if (_warnedNames.Add(name)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("No piece named '" + name + "' found in your build tools. Use the prefab name, the $piece_... localization key, or the English display name.")); } ShowMessage(player, "Unknown piece '" + name + "'"); } private static bool TryResolve(Player player, string name, out ItemData tool, out Piece piece) { tool = null; piece = null; Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return false; } List<ItemData> allItems = inventory.GetAllItems(); if (allItems == null) { return false; } ItemData val = null; Piece val2 = null; foreach (ItemData item in allItems) { if (item == null || item.m_shared == null) { continue; } PieceTable buildPieces = item.m_shared.m_buildPieces; if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null) { continue; } Piece val3 = FindPiece(buildPieces, name); if (!((Object)(object)val3 == (Object)null)) { if (IsBuildTool(item)) { tool = item; piece = val3; return true; } if (val == null) { val = item; val2 = val3; } } } tool = val; piece = val2; return (Object)(object)piece != (Object)null; } private static bool IsBuildTool(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name.IndexOf("hammer", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (item.m_shared.m_name != null) { return item.m_shared.m_name.IndexOf("hammer", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static Piece FindPiece(PieceTable table, string name) { foreach (GameObject piece in table.m_pieces) { if (!((Object)(object)piece == (Object)null)) { Piece component = piece.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && Matches(component, piece, name)) { return component; } } } return null; } private static bool Matches(Piece piece, GameObject go, string name) { if (string.Equals(((Object)go).name, name, StringComparison.OrdinalIgnoreCase)) { return true; } string name2 = piece.m_name; if (string.IsNullOrEmpty(name2)) { return false; } if (string.Equals(name2, name, StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(name2.TrimStart(new char[1] { '$' }), name, StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(name2, "$" + name, StringComparison.OrdinalIgnoreCase)) { return true; } Localization instance = Localization.instance; if (instance == null) { return false; } string a = instance.Localize(name2); if (string.Equals(a, name, StringComparison.OrdinalIgnoreCase)) { return true; } if (!string.Equals(a, name2, StringComparison.Ordinal)) { return false; } string text = name2.TrimStart(new char[1] { '$' }); a = instance.Localize(text); return string.Equals(a, name, StringComparison.OrdinalIgnoreCase); } private static string DescribePiece(Piece piece) { if ((Object)(object)piece == (Object)null) { return string.Empty; } string name = piece.m_name; Localization instance = Localization.instance; if (!string.IsNullOrEmpty(name) && instance != null) { string text = instance.Localize(name); if (string.Equals(text, name, StringComparison.Ordinal)) { text = instance.Localize(name.TrimStart(new char[1] { '$' })); } if (!string.IsNullOrEmpty(text) && !string.Equals(text, name, StringComparison.Ordinal)) { return text; } } return ((Object)piece).name; } private static string DescribeTool(ItemData item) { if (item == null) { return "the tool"; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } if (!string.IsNullOrEmpty(item.m_shared?.m_name)) { return item.m_shared.m_name; } return "the tool"; } }