using 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)
{
}
}
}