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 YetAnotherSellMod v1.2.0
baer1.YetAnotherSellMod.dll
Decompiled 10 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ChatCommandAPI; using HarmonyLib; using Microsoft.CodeAnalysis; 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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("baer1.YetAnotherSellMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0+4ec4cca9b5a811f32507d68c29cf50d0c5467977")] [assembly: AssemblyProduct("LethalSellMod")] [assembly: AssemblyTitle("baer1.YetAnotherSellMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 LethalSellMod { [BepInPlugin("baer1.YetAnotherSellMod", "LethalSellMod", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LethalSellMod : BaseUnityPlugin { private ConfigEntry<string> itemBlacklist = null; public static LethalSellMod Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal string[] ItemBlacklist => csv(itemBlacklist.Value); private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; itemBlacklist = ((BaseUnityPlugin)this).Config.Bind<string>("Items", "ItemBlacklist", csv(new string[1] { "ShotgunItem" }), "Items to never sell by internal name (comma-separated)"); new SellCommand(); Logger.LogInfo((object)"baer1.YetAnotherSellMod v1.2.0 has loaded!"); } private static string csv(string[] e) { return GeneralExtensions.Join<string>((IEnumerable<string>)e, (Func<string, string>)null, ","); } private static string[] csv(string e) { return e.Split(','); } } public class SellCommand : Command { private const string CLONE = "(Clone)"; public override string Name => "Sell"; public override string Description => "Sells items on 71-Gordion"; public override string[] Syntax => new string[2] { "[value]", "{ quota | all }" }; public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error) { error = "Invalid arguments"; int itemCount; switch (args.Length) { case 0: { if (!OpenDoor(out error, out itemCount, out var totalValue)) { return false; } ChatCommandAPI.Print("Selling " + a(itemCount) + " with a total value of " + b(totalValue)); return true; } case 1: { string text = args[0].ToLower(); string text2 = text; int? num; if (!(text2 == "quota")) { if (text2 == "all") { num = null; } else { if (!int.TryParse(args[0], out var result)) { return false; } error = "Value must be a positive integer"; if (result < 1) { return false; } num = result; } } else { num = TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled; error = "Quota is already fulfilled"; if (num < 1) { return false; } } error = "Selling desk not found"; DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>(); if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)val == (Object)null) { return false; } error = "No items found"; List<GrabbableObject> list = ItemsForValue(num, val); if (list == null) { return false; } error = "You can't afford to sell that amount"; if (list.Count == 0) { return false; } error = "Error selling items"; if (!SellItems(list, val, out itemCount)) { return false; } ChatCommandAPI.Print("Put " + a(itemCount) + " worth " + b(list) + " on the desk"); return true; } default: return false; } } private static string a(int itemCount) { return itemCount + ((itemCount == 1) ? " item" : " items"); } private static string b(List<GrabbableObject> items) { return items.Sum((GrabbableObject i) => i.scrapValue) + (Mathf.Approximately(StartOfRound.Instance.companyBuyingRate, 1f) ? "" : $" ({(int)((float)items.Sum((GrabbableObject i) => i.scrapValue) * StartOfRound.Instance.companyBuyingRate)})"); } private static string b(int totalValue) { return totalValue + (Mathf.Approximately(StartOfRound.Instance.companyBuyingRate, 1f) ? "" : $" ({(int)((float)totalValue * StartOfRound.Instance.companyBuyingRate)})"); } private static List<GrabbableObject>? ItemsForValue(int? value, DepositItemsDesk desk) { LethalSellMod.Logger.LogDebug((object)string.Format(">> ItemsForValue({0}, {1})", (!value.HasValue) ? "null" : ((object)value), desk)); if (value.HasValue && value.GetValueOrDefault() == 0) { LethalSellMod.Logger.LogDebug((object)"<< ItemsForValue -> null (no value)"); return null; } GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>(); LethalSellMod.Logger.LogDebug((object)$" max value: {array.Sum((GrabbableObject i) => i.scrapValue)} items:{c(array)}"); if (array == null || array.Length == 0) { LethalSellMod.Logger.LogDebug((object)("<< ItemsForValue -> null (items is empty) items:" + c(array))); return null; } array = FilterItems(array, desk); LethalSellMod.Logger.LogDebug((object)$" post-filter max value: {array.Sum((GrabbableObject i) => i.scrapValue)} items:{c(array)}"); if (array.Length == 0) { LethalSellMod.Logger.LogDebug((object)("<< ItemsForValue -> null (filtered items is empty) items:" + c(array))); return null; } if (!value.HasValue) { LethalSellMod.Logger.LogDebug((object)("<< ItemsForValue -> " + c(array) + " (no calculations required > all)")); return array.ToList(); } if (array.Length == 1 && array[0].scrapValue >= value) { LethalSellMod.Logger.LogDebug((object)("<< ItemsForValue -> " + c(array) + " (no calculations required > 1 item)")); return array.ToList(); } value = (int)Math.Ceiling(((float?)value / StartOfRound.Instance.companyBuyingRate).Value); List<GrabbableObject> bestSubset = new List<GrabbableObject>(); LethalSellMod.Logger.LogDebug((object)(SmartCalculation(array, value.Value, ref bestSubset) ? ("<< ItemsForValue -> " + c(bestSubset) + " (found best match)") : ("<< ItemsForValue -> " + c(bestSubset)))); return bestSubset; } private static bool SmartCalculation(GrabbableObject[] items, int value, ref List<GrabbableObject> bestSubset) { GrabbableObject[] items2 = items; items2 = items2.OrderByDescending((GrabbableObject i) => i.scrapValue).ToArray(); int num = int.MinValue; int num2 = 0; List<int> baseItems = new List<int>(); while (num2 <= value - 50) { bool flag = false; for (int l = 0; l < items2.Length; l++) { if (!baseItems.Contains(l) && (num2 + items2[l].scrapValue <= Math.Max(value - 50, 0) || num2 + items2[l].scrapValue == value)) { num2 += items2[l].scrapValue; int num3 = value - 50 - num2; baseItems.Add(l); LethalSellMod.Logger.LogDebug((object)string.Format(" Found {0}base match: {1} items for {2} value ({3} requested, diff:{4}, bestDiff:{5})", (num == int.MinValue) ? "" : ((num3 == 0) ? "best " : "better "), baseItems.Count, num2, value, num3, num)); num = num3; flag = true; break; } } if (flag) { continue; } break; } int num4 = value - num2; num = -num4; List<GrabbableObject> collection = (bestSubset = baseItems.Select((int i) => items2[i]).ToList()); items2 = items2.Where((GrabbableObject _, int i) => !baseItems.Contains(i)).ToArray(); LethalSellMod.Logger.LogDebug((object)$" Finished base calculation ({baseItems.Count} items for {num2} value, missing {num4} value, got {items2.Length} items to work with)"); if (num4 == 0) { return true; } if (items2.Length == 0) { if (num4 > 0) { bestSubset = new List<GrabbableObject>(); } return false; } int k; for (k = 0; k < (int)Math.Pow(2.0, items2.Length); k++) { int num5 = items2.Where((GrabbableObject _, int j) => (k & (int)Math.Pow(2.0, j)) != 0).Sum((GrabbableObject t) => t.scrapValue); int num6 = num4 - num5; if (num6 <= 0 && num6 > num) { bestSubset = new List<GrabbableObject>(); bestSubset.AddRange(items2.Where((GrabbableObject _, int j) => (k & (int)Math.Pow(2.0, j)) != 0)); LethalSellMod.Logger.LogDebug((object)string.Format(" Found {0}match: {1} items for {2} value ({3} requested, diff:{4}, bestDiff:{5})", (num == int.MinValue) ? "" : ((num6 == 0) ? "best " : "better "), bestSubset.Count + baseItems.Count, num5 + num2, value, num6, num)); if (num6 == 0) { bestSubset.AddRange(collection); return true; } num = num6; } } if (num > 0) { bestSubset = new List<GrabbableObject>(); return false; } bestSubset.AddRange(collection); return false; } private static string c(IList? list) { return (list == null) ? "null" : string.Format("{0}{1}[{2}]", list.GetType().Name, (list.GetType().GetGenericArguments().Length == 0) ? "" : ("<" + GeneralExtensions.Join<Type>((IEnumerable<Type>)list.GetType().GetGenericArguments(), (Func<Type, string>)null, ", ") + ">"), list.Count); } private static bool SellItems(List<GrabbableObject> items, DepositItemsDesk desk, out int itemCount) { //IL_0048: 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) //IL_0052: 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) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0074: 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_0083: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) GameNetworkManager.Instance.localPlayerController.DropAllHeldItemsAndSync(); itemCount = 0; RaycastHit val2 = default(RaycastHit); foreach (GrabbableObject item in items) { if (!((Object)(object)item == (Object)null)) { itemCount++; Vector3 val = RoundManager.RandomPointInBounds(((Collider)desk.triggerCollider).bounds); Bounds bounds = ((Collider)desk.triggerCollider).bounds; val.y = ((Bounds)(ref bounds)).min.y; if (Physics.Raycast(new Ray(val + Vector3.up * 3f, Vector3.down), ref val2, 8f, 1048640, (QueryTriggerInteraction)2)) { val = ((RaycastHit)(ref val2)).point; } val.y += item.itemProperties.verticalOffset; val = ((Component)desk.deskObjectsContainer).transform.InverseTransformPoint(val); desk.AddObjectToDeskServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject)); GameNetworkManager.Instance.localPlayerController.PlaceGrabbableObject(((Component)desk.deskObjectsContainer).transform, val, false, item); GameNetworkManager.Instance.localPlayerController.PlaceObjectServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject), NetworkObjectReference.op_Implicit(desk.deskObjectsContainer), val, false); } } return true; } public static string RemoveClone(string name) { string result; if (!name.EndsWith("(Clone)")) { result = name; } else { int length = "(Clone)".Length; result = name.Substring(0, name.Length - length); } return result; } private static GrabbableObject[] FilterItems(GrabbableObject[] items, DepositItemsDesk desk) { DepositItemsDesk desk2 = desk; return (from i in items.Where(delegate(GrabbableObject i) { int result; if (i != null && i.scrapValue > 0 && !i.isHeld && !i.isPocketed) { Item itemProperties = i.itemProperties; if (itemProperties != null && itemProperties.isScrap) { result = ((!desk2.itemsOnCounter.Contains(i)) ? 1 : 0); goto IL_0045; } } result = 0; goto IL_0045; IL_0045: return (byte)result != 0; }) where !LethalSellMod.Instance.ItemBlacklist.Contains(RemoveClone(((Object)i).name)) select i).ToArray(); } private static bool OpenDoor(out string error, out int itemCount, out int totalValue) { itemCount = 0; totalValue = 0; error = "Selling desk not found"; DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>(); if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)val == (Object)null) { return false; } itemCount = val.itemsOnCounter.Count; totalValue = val.itemsOnCounter.Sum((GrabbableObject i) => i.scrapValue); error = "No items on desk"; if (itemCount == 0) { return false; } error = "Door already open"; if (val.doorOpen) { return false; } val.SetTimesHeardNoiseServerRpc(5f); return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "baer1.YetAnotherSellMod"; public const string PLUGIN_NAME = "LethalSellMod"; public const string PLUGIN_VERSION = "1.2.0"; } }