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 Quick Buy Menu v2.0.0
BepInEx/plugins/QuickBuyMenu.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Lib; using CSync.Util; using GameNetcodeStuff; using HarmonyLib; using LC_API.ClientAPI; using LC_API.GameInterfaceAPI.Features; using LethalNetworkAPI; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("QuickBuyMenu")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("An experimental mod for providing an alternative means to purchase handheld items instantly from the Terminal.")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: AssemblyInformationalVersion("2.0.0")] [assembly: AssemblyProduct("Quick Buy Menu")] [assembly: AssemblyTitle("QuickBuyMenu")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 QuickBuyMenu { [BepInPlugin("Quick.Buy.Menu", "Quick Buy Meny", "2.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public struct ClientItemRequestParams : INetworkSerializeByMemcpy { public string ItemName; public int clientIndex; private unsafe void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter { //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) serializer.SerializeValue(ref ItemName, false); ((BufferSerializer<int>*)(&serializer))->SerializeValue<int>(ref clientIndex, default(ForPrimitives)); } } private static Plugin Instance; internal static ManualLogSource Log; private LNetworkMessage<ClientItemRequestParams> clientItemSpawnRequest; private LNetworkMessage<int> syncCredits; private List<string> blackListedItems; public static QuickBuyModConfig Config { get; private set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } Log = ((BaseUnityPlugin)this).Logger; Log.LogDebug((object)"Plugin QuickBuyMenu is loaded!"); Config = new QuickBuyModConfig(((BaseUnityPlugin)this).Config); blackListedItems = (from item in Config.quickBuyItemBlacklist.Value.Split(',') select item.Trim() into item where !string.IsNullOrEmpty(item) select item).ToList(); CommandHandler.RegisterCommand("quickbuy", new List<string> { "qb", "buy", "qbuy" }, (Action<string[]>)RunQuickBuy); CommandHandler.RegisterCommand("price-check", new List<string> { "qc", "inquire", "check", "pc" }, (Action<string[]>)RunPriceCheck); clientItemSpawnRequest = LNetworkMessage<ClientItemRequestParams>.Create("clientItemSpawnRequest", (Action<ClientItemRequestParams, ulong>)delegate(ClientItemRequestParams clientRequest, ulong clientId) { //IL_0062: 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_006f: Unknown result type (might be due to invalid IL or missing references) Player val = Player.Get(GameNetworkManager.Instance.localPlayerController.playersManager.allPlayerScripts[clientRequest.clientIndex]); GameObject spawnPrefab = ((IEnumerable<Item>)Object.FindObjectOfType<Terminal>().buyableItemsList).FirstOrDefault((Func<Item, bool>)((Item kw) => ((Object)kw).name.Equals(clientRequest.ItemName))).spawnPrefab; if ((Object)(object)spawnPrefab != (Object)null) { GameObject val2 = Object.Instantiate<GameObject>(spawnPrefab, Vector3.zero, default(Quaternion)); val2.GetComponent<NetworkObject>().Spawn(false); Item component = val2.GetComponent<Item>(); component.GiveTo(val, true); } }, (Action<ClientItemRequestParams>)null, (Action<ClientItemRequestParams, ulong>)null); syncCredits = LNetworkMessage<int>.Create("syncCredits", (Action<int, ulong>)delegate(int credits, ulong clientId) { ((BaseUnityPlugin)this).Logger.LogDebug((object)$"Server received update credits: {credits}"); Object.FindObjectOfType<Terminal>().groupCredits = credits; }, (Action<int>)delegate(int credits) { ((BaseUnityPlugin)this).Logger.LogDebug((object)$"Client received update credits: {credits}"); Object.FindObjectOfType<Terminal>().groupCredits = credits; }, (Action<int, ulong>)delegate(int credits, ulong clientId) { ((BaseUnityPlugin)this).Logger.LogDebug((object)$"Client - client received update credits: {credits}"); Object.FindObjectOfType<Terminal>().groupCredits = credits; }); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } private void RunQuickBuy(string[] obj) { Terminal val = Object.FindObjectOfType<Terminal>(); if (!IsQuickBuyAllowed()) { chatMessageHandler("You can only use quick buy commands on the ship.", isWarning: true); } else { if (obj.Length == 0) { return; } int quantity = GetQuantity(obj); string text = obj[0].Trim(); ((BaseUnityPlugin)this).Logger.LogDebug((object)(" item arg: " + obj[0])); Item itemMatch = FindItemMatch(val, text); if ((Object)(object)itemMatch == (Object)null) { chatMessageHandler("Item " + text + " not found.", isWarning: true); } else if (blackListedItems.Exists((string item) => item.Equals(itemMatch.itemName, StringComparison.OrdinalIgnoreCase))) { chatMessageHandler(itemMatch.itemName + " is blacklisted.", isWarning: true); } else if (CheckPlayerInventory(quantity)) { if (!HasEnoughCredits(val, itemMatch, quantity, out var itemCost, out var adjustedCredits)) { chatMessageHandler($"Not Enough Credits\n\nTotal Cost: ${itemCost}\nCredits: ${val.groupCredits}", isWarning: true); } else { ProcessQuickBuy(val, itemMatch, quantity, itemCost, adjustedCredits); } } } } private void RunPriceCheck(string[] obj) { Terminal val = Object.FindObjectOfType<Terminal>(); if (!IsQuickBuyAllowed()) { chatMessageHandler("You can only use quick buy commands on the ship.", isWarning: true); } else if (obj.Length != 0) { string text = obj[0].Trim(); int quantity = GetQuantity(obj); Item itemMatch = FindItemMatch(val, text); float itemCost; int adjustedCredits; if ((Object)(object)itemMatch == (Object)null) { chatMessageHandler("Item " + text + " not found.", isWarning: true); } else if (blackListedItems.Exists((string item) => item.Equals(itemMatch.itemName, StringComparison.OrdinalIgnoreCase))) { chatMessageHandler(itemMatch.itemName + " is blacklisted.", isWarning: true); } else if (!HasEnoughCredits(val, itemMatch, quantity, out itemCost, out adjustedCredits)) { chatMessageHandler($"Price Check\nNot Enough Credits\n\nItem: {itemMatch.itemName}\nQuantity: {quantity}\nTotal Cost: ${itemCost}\nGroup Credits: ${val.groupCredits}", isWarning: true); } else { chatMessageHandler($"Price Check\n\nItem: {itemMatch.itemName}\nQuantity: {quantity}\nTotal Cost: ${itemCost}\nGroup Credits: ${val.groupCredits}"); } } } private bool IsQuickBuyAllowed() { return Config.allowQuickBuyOffShip.Value || GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom; } private int GetQuantity(string[] obj) { int result; return (obj.Length != 2 || !int.TryParse(obj[1], out result)) ? 1 : result; } private Item FindItemMatch(Terminal terminal, string itemKeyword) { return ((IEnumerable<Item>)terminal.buyableItemsList).FirstOrDefault((Func<Item, bool>)((Item kw) => ((Object)kw).name.Contains(itemKeyword, StringComparison.OrdinalIgnoreCase))) ?? ((IEnumerable<Item>)terminal.buyableItemsList).FirstOrDefault((Func<Item, bool>)((Item kw) => ((Object)kw).name.Equals(itemKeyword, StringComparison.OrdinalIgnoreCase))); } private bool HasEnoughCredits(Terminal terminal, Item itemMatch, int quantity, out float itemCost, out int adjustedCredits) { itemCost = (float)itemMatch.creditsWorth * ((float)terminal.itemSalesPercentages[Array.IndexOf(terminal.buyableItemsList, itemMatch)] / 100f) * (float)quantity; adjustedCredits = terminal.groupCredits - (int)itemCost; return adjustedCredits >= 0; } private bool CheckPlayerInventory(int quantity) { Player val = Player.Get(GameNetworkManager.Instance.localPlayerController); if (val.Inventory.GetFirstEmptySlot() == -1) { chatMessageHandler("Inventory is Full.", isWarning: true); return false; } Log.LogDebug((object)$"Item slots length: {val.PlayerController.ItemSlots.Length}"); int num = val.Inventory.Items.Where((Item item) => (Object)(object)item != (Object)null).ToArray().Length; int num2 = val.PlayerController.ItemSlots.Length - num; if (quantity > val.PlayerController.ItemSlots.Length - num) { chatMessageHandler("Not enough inventory space for this order.", isWarning: true); return false; } return true; } private void ProcessQuickBuy(Terminal terminal, Item itemMatch, int quantity, float itemCost, int adjustedCredits) { int clientIndex = Array.FindIndex(GameNetworkManager.Instance.localPlayerController.playersManager.allPlayerScripts, (PlayerControllerB player) => player.actualClientId.Equals(GameNetworkManager.Instance.localPlayerController.actualClientId)); for (int i = 0; i < quantity; i++) { ClientItemRequestParams clientItemRequestParams = default(ClientItemRequestParams); clientItemRequestParams.clientIndex = clientIndex; clientItemRequestParams.ItemName = ((Object)itemMatch).name; clientItemSpawnRequest.SendServer(clientItemRequestParams); } terminal.groupCredits = adjustedCredits; SyncCredits(adjustedCredits); chatMessageHandler($"Order Summary\n\n{itemMatch.itemName}\nQuantity: {quantity}\nTotal: ${(int)itemCost}\nCredits: ${adjustedCredits}"); } private void SyncCredits(int adjustedCredits) { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { syncCredits.SendClients(adjustedCredits); } else { syncCredits.SendOtherClients(adjustedCredits); } } private void chatMessageHandler(string message, bool isWarning = false) { string text = (isWarning ? "red" : "green"); string text2 = "<color=\"" + text + "\"><b>Quick Buy</b>\n" + message + "</color>"; if (HUDManager.Instance.lastChatMessage == text2) { HUDManager.Instance.lastChatMessage = ""; } HUDManager.Instance.AddChatMessage(text2, ""); AudioClip[] array = (isWarning ? HUDManager.Instance.warningSFX : HUDManager.Instance.tipsSFX); RoundManager.PlayRandomClip(HUDManager.Instance.UIAudio, array, false, 1f, 0, 1000); quickBuyChatMessageDelayHandler(Config.quickBuyMessagesFadeDelay.Value); } private async void quickBuyChatMessageDelayHandler(int seconds) { await Task.Delay(seconds * 1000); int chatIndex = HUDManager.Instance.ChatMessageHistory.FindIndex((string chat) => chat.Contains("<b>Quick Buy</b>")); if (chatIndex != -1) { HUDManager.Instance.ChatMessageHistory.RemoveAt(chatIndex); ((TMP_Text)HUDManager.Instance.chatText).text = ""; for (int i = 0; i < HUDManager.Instance.ChatMessageHistory.Count; i++) { TextMeshProUGUI textMeshProUGUI = HUDManager.Instance.chatText; ((TMP_Text)textMeshProUGUI).text = ((TMP_Text)textMeshProUGUI).text + "\n" + HUDManager.Instance.ChatMessageHistory[i]; } } } } [DataContract] public class QuickBuyModConfig : SyncedConfig<QuickBuyModConfig> { [DataMember] public SyncedEntry<bool> allowQuickBuyOffShip { get; private set; } public ConfigEntry<int> quickBuyMessagesFadeDelay { get; private set; } [DataMember] public SyncedEntry<string> quickBuyItemBlacklist { get; private set; } [DataMember] public SyncedEntry<float> EXAMPLE_VAR { get; private set; } public QuickBuyModConfig(ConfigFile cfg) : base("Quick Buy Menu") { ConfigManager.Register<QuickBuyModConfig>(this); allowQuickBuyOffShip = Extensions.BindSyncedEntry<bool>(cfg, "General", "AllowQuickBuyOffShip", false, "Boolean that lets you buy items off ship. For balancing this is set to false as default."); quickBuyMessagesFadeDelay = cfg.Bind<int>("General", "quickBuyMessagesFadeDelay", 5, "Timer in seconds for how long the Quick Buy chat messages should appear before they are deleted."); quickBuyItemBlacklist = Extensions.BindSyncedEntry<string>(cfg, "General", "QuickBuyItemBlacklist", "", "Comma Seperated List of Items to be blacklisted by Quick Buy. Example: 'Walkie-Talkie,FlashLight,Boombox'"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "QuickBuyMenu"; public const string PLUGIN_NAME = "Quick Buy Menu"; public const string PLUGIN_VERSION = "2.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }