using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using ConditionalConfigSync; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Buy Dvergr Extractor Needle")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Buy Dvergr Extractor Needle")] [assembly: AssemblyCopyright("Copyright © 2024-2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1bd1a4b7-cfc5-48c2-b443-1c91bd448dba")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 BuyExtractorNeedle { public class BuyAndDestroy : MonoBehaviour, Hoverable, Interactable { internal sealed class PaymentItem { internal readonly string PrefabName; internal readonly string SharedName; internal int Amount; internal PaymentItem(string prefabName, string sharedName, int amount) { PrefabName = prefabName; SharedName = sharedName; Amount = amount; } internal PaymentItem Clone(int amount) { return new PaymentItem(PrefabName, SharedName, amount); } } internal sealed class PurchaseData { internal readonly string BuyerName; internal readonly string PurchasedPrefabName; internal readonly List Payment; internal PurchaseData(string buyerName, string purchasedPrefabName, List payment) { BuyerName = buyerName; PurchasedPrefabName = purchasedPrefabName; Payment = payment ?? new List(); } } internal const float DvergrSearchRadius = 30f; private const string PurchaseRpc = "BEN_BuyAndRemove"; private static readonly int PurchaseProcessedZdoKey = StringExtensionMethods.GetStableHashCode("shudnal.BuyExtractorNeedle.PurchaseProcessed"); public string m_text = ""; public Destructible m_destructible; public WearNTear m_wnt; public ZNetView m_nview; public string m_requirements; public string m_description; public int m_myIndex = -1; public static readonly List s_allInstances = new List(); public static readonly List s_randomBuy = new List { "$npc_haldor_random_buy1", "$npc_haldor_random_buy3", "$npc_haldor_random_buy4", "$npc_haldor_random_buy5", "$npc_haldor_random_sell1", "$npc_haldor_random_sell2", "$npc_haldor_random_greet4", "$npc_haldor_random_sell4" }; public static EffectList s_randomSellFX; public void Awake() { EnsureSellEffects(); IDestructible component = ((Component)this).GetComponent(); m_destructible = (Destructible)(object)((component is Destructible) ? component : null); m_wnt = (WearNTear)(object)((component is WearNTear) ? component : null); s_allInstances.Add(this); m_myIndex = s_allInstances.Count - 1; m_requirements = BuyExtractorNeedle.requirements.Value; m_nview = (((Object)(object)m_destructible != (Object)null) ? m_destructible.m_nview : (((Object)(object)m_wnt != (Object)null) ? m_wnt.m_nview : null)); if ((Object)(object)m_nview != (Object)null && m_nview.GetZDO() != null) { m_nview.Register("BEN_BuyAndRemove", (Action)RPC_BuyAndRemove); } } public void OnDestroy() { if (m_myIndex >= 0 && m_myIndex < s_allInstances.Count) { int index = s_allInstances.Count - 1; s_allInstances[m_myIndex] = s_allInstances[index]; s_allInstances[m_myIndex].m_myIndex = m_myIndex; s_allInstances.RemoveAt(index); m_myIndex = -1; } } public string GetHoverText() { if ((Object)(object)m_destructible == (Object)null && (Object)(object)m_wnt == (Object)null) { return GetHoverName(); } if (string.IsNullOrWhiteSpace(m_description) && !string.IsNullOrWhiteSpace(m_requirements)) { m_description = GetDescription(m_requirements); } string text = (string.IsNullOrWhiteSpace(m_description) ? "$piece_itemstand_take" : ("$store_buy " + m_description)); return Localization.instance.Localize(m_text + "\n[$KEY_Use] " + text); } public string GetHoverName() { return Localization.instance.Localize(m_text); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if (hold || alt || ((Object)(object)m_destructible == (Object)null && (Object)(object)m_wnt == (Object)null) || (Object)(object)user == (Object)null) { return false; } if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return false; } string buyerName = GetBuyerName(user); List requirements = GetRequirements(m_requirements); if (!HasNearbyDvergr(((Component)this).transform.position)) { Remove(Array.Empty(), buyerName); return true; } Inventory inventory = user.GetInventory(); if (requirements.Count > 0 && requirements.Any((PaymentItem item) => inventory.CountItems(item.SharedName, -1, true) < item.Amount)) { PrivateArea.OnObjectDamaged(((Component)this).transform.position, (Character)(object)user, false); return true; } foreach (PaymentItem item in requirements) { inventory.RemoveItem(item.SharedName, item.Amount, -1, true); } if (requirements.Count > 0 && (Object)(object)StoreGui.instance != (Object)null) { StoreGui.instance.m_sellEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1); } Remove(requirements, buyerName); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void Remove(IEnumerable payment, string buyerName) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { string prefabName = m_nview.GetPrefabName(); m_nview.InvokeRPC("BEN_BuyAndRemove", new object[1] { CreatePurchasePackage(buyerName, prefabName, payment) }); } } private void RPC_BuyAndRemove(long sender, ZPackage package) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner()) { return; } PurchaseData purchaseData = ReadPurchasePackage(package); List payment = purchaseData.Payment; ZDO zDO = m_nview.GetZDO(); if (zDO == null) { return; } if (zDO.GetBool(PurchaseProcessedZdoKey, false)) { RefundPayment(payment); if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("A repeated purchase of '" + purchaseData.PurchasedPrefabName + "' by player '" + purchaseData.BuyerName + "' was rejected and its payment was refunded: " + FormatPayment(payment) + "."); } return; } zDO.Set(PurchaseProcessedZdoKey, true); DvergrPaidItemStorage dvergrPaidItemStorage = DvergrPaidItemStorage.FindClosest(((Component)this).transform.position, 30f); if ((Object)(object)dvergrPaidItemStorage == (Object)null) { RefundPayment(payment); if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo("Player '" + purchaseData.BuyerName + "' obtained '" + purchaseData.PurchasedPrefabName + "' for free because no Dvergr was available to accept payment."); } DestroyPurchasedObject(); } else if (!dvergrPaidItemStorage.AcceptPurchase(purchaseData)) { RefundPayment(payment); if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Purchase of '" + purchaseData.PurchasedPrefabName + "' by player '" + purchaseData.BuyerName + "' could not be assigned to " + dvergrPaidItemStorage.GetLogDescription() + ". Refunded payment: " + FormatPayment(payment) + "."); } DestroyPurchasedObject(); } else { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo("Player '" + purchaseData.BuyerName + "' bought '" + purchaseData.PurchasedPrefabName + "' for " + FormatPayment(payment) + ". Primary payment recipient: " + dvergrPaidItemStorage.GetLogDescription() + "."); } DestroyPurchasedObject(); } } private void DestroyPurchasedObject() { if ((Object)(object)m_destructible != (Object)null) { m_destructible.Destroy((HitData)null); } else if ((Object)(object)m_wnt != (Object)null) { m_wnt.Destroy((HitData)null, false); } } private void RefundPayment(IEnumerable payment) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) foreach (PaymentItem item in payment) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item.PrefabName) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if (!((Object)(object)val2 == (Object)null) && val2.m_itemData != null && val2.m_itemData.m_shared != null) { int val3 = Math.Max(1, val2.m_itemData.m_shared.m_maxStackSize); int num = item.Amount; while (num > 0) { int num2 = Math.Min(val3, num); DropItemStack(val, val2, num2, ((Component)this).transform.position + Vector3.up, Quaternion.identity); num -= num2; } } } } internal static ItemDrop DropItemStack(GameObject prefab, ItemDrop itemDrop, int amount, Vector3 position, Quaternion rotation) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null || (Object)(object)itemDrop == (Object)null || itemDrop.m_itemData == null || amount <= 0) { return null; } ItemData val = itemDrop.m_itemData.Clone(); val.m_dropPrefab = prefab; return ItemDrop.DropItem(val, amount, position, rotation); } internal static void PlaySaleResponse(NpcTalk npcTalk, int lineIndex) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)npcTalk == (Object)null) && s_randomBuy.Count != 0) { EnsureSellEffects(); s_randomSellFX.Create(((Component)npcTalk).transform.position, Quaternion.identity, (Transform)null, 1f, -1); int index = Mathf.Clamp(lineIndex, 0, s_randomBuy.Count - 1); npcTalk.Say(s_randomBuy[index], "Talk"); } } private static void EnsureSellEffects() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (s_randomSellFX == null) { object obj; if (!((Object)(object)ZNetScene.instance != (Object)null)) { obj = null; } else { GameObject prefab = ZNetScene.instance.GetPrefab("Haldor"); obj = ((prefab != null) ? prefab.GetComponent() : null); } Trader val = (Trader)obj; s_randomSellFX = (EffectList)(((Object)(object)val != (Object)null) ? ((object)val.m_randomSellFX) : ((object)new EffectList())); } } private static bool HasNearbyDvergr(Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return (Object)(object)DvergrPaidItemStorage.FindClosest(position, 30f) != (Object)null; } private static string GetBuyerName(Humanoid user) { Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val != (Object)null) { string playerName = val.GetPlayerName(); if (!string.IsNullOrWhiteSpace(playerName)) { return playerName; } } return (!string.IsNullOrWhiteSpace(((Object)user).name)) ? ((Object)user).name : "Unknown player"; } private static string GetDescription(string requirements) { return string.Join(", ", (from item in GetRequirements(requirements) select item.SharedName + " x" + item.Amount).ToArray()); } private static List GetRequirements(string requirements) { List list = new List(); Dictionary dictionary = new Dictionary(StringComparer.Ordinal); if (string.IsNullOrWhiteSpace(requirements) || (Object)(object)ObjectDB.instance == (Object)null) { return list; } string[] array = requirements.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length != 2 || !int.TryParse(array2[1].Trim(), out var result) || result <= 0) { continue; } string text2 = array2[0].Trim(); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text2); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); string text3 = (((Object)(object)val != (Object)null && val.m_itemData != null && val.m_itemData.m_shared != null) ? val.m_itemData.m_shared.m_name : null); if (!string.IsNullOrEmpty(text3)) { if (dictionary.TryGetValue(text2, out var value)) { value.Amount = (int)Math.Min(2147483647L, (long)value.Amount + (long)result); continue; } PaymentItem paymentItem = new PaymentItem(text2, text3, result); dictionary.Add(text2, paymentItem); list.Add(paymentItem); } } return list; } internal static ZPackage CreatePurchasePackage(string buyerName, string purchasedPrefabName, IEnumerable payment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(buyerName ?? "Unknown player"); val.Write(purchasedPrefabName ?? "Unknown prefab"); WritePayment(val, payment); return val; } internal static PurchaseData ReadPurchasePackage(ZPackage package) { if (package == null) { return new PurchaseData("Unknown player", "Unknown prefab", new List()); } try { string buyerName = package.ReadString(); string purchasedPrefabName = package.ReadString(); return new PurchaseData(buyerName, purchasedPrefabName, ReadPayment(package)); } catch (Exception ex) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Failed to read purchase package: " + ex.Message); } return new PurchaseData("Unknown player", "Unknown prefab", new List()); } } internal static string FormatPayment(IEnumerable payment) { if (payment == null) { return "nothing"; } string[] array = (from item in payment where item != null && item.Amount > 0 select item.PrefabName + " x" + item.Amount).ToArray(); return (array.Length != 0) ? string.Join(", ", array) : "nothing"; } private static void WritePayment(ZPackage package, IEnumerable payment) { List list = ((payment != null) ? payment.Where((PaymentItem item) => item != null && item.Amount > 0).ToList() : new List()); package.Write(list.Count); foreach (PaymentItem item in list) { package.Write(item.PrefabName); package.Write(item.Amount); } } private static List ReadPayment(ZPackage package) { List list = new List(); int num = Mathf.Clamp(package.ReadInt(), 0, 64); for (int i = 0; i < num; i++) { string text = package.ReadString(); int num2 = package.ReadInt(); GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); string text2 = (((Object)(object)val2 != (Object)null && val2.m_itemData != null && val2.m_itemData.m_shared != null) ? val2.m_itemData.m_shared.m_name : null); if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && num2 > 0) { list.Add(new PaymentItem(text, text2, num2)); } } return list; } public static List GetAllInstances() { return s_allInstances; } public static void UpdateDescription() { foreach (BuyAndDestroy s_allInstance in s_allInstances) { s_allInstance.m_requirements = BuyExtractorNeedle.requirements.Value; s_allInstance.m_description = ""; } } } [BepInPlugin("shudnal.BuyExtractorNeedle", "Buy Dvergr Extractor Needle", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BuyExtractorNeedle : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class ZNetSceneAwakePatch { private static void Postfix(ZNetScene __instance) { ApplyConfiguredPrefabs(__instance); } } public const string pluginID = "shudnal.BuyExtractorNeedle"; public const string pluginName = "Buy Dvergr Extractor Needle"; public const string pluginVersion = "1.1.0"; private readonly Harmony harmony = new Harmony("shudnal.BuyExtractorNeedle"); internal static readonly ConfigSync configSync = new ConfigSync("shudnal.BuyExtractorNeedle") { DisplayName = "Buy Dvergr Extractor Needle", CurrentVersion = "1.1.0", MinimumRequiredVersion = "1.1.0", ModRequired = true }; public static BuyExtractorNeedle instance; public static ConfigEntry configLocked; public static ConfigEntry requirements; public static ConfigEntry targetPrefabs; public static ConfigEntry loggingEnabled; private static readonly Dictionary managedPrefabTexts = new Dictionary(StringComparer.Ordinal); private void Awake() { instance = this; ConfigInit(); ((ConditionalConfigSync)configSync).AddLockingConfigEntry(configLocked); harmony.PatchAll(); Game.isModded = true; } private void ConfigInit() { configLocked = BindConfig("General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only."); requirements = BindConfig("General", "Required items", "Coins:4000", "Items required to buy a configured crate. Use prefab names separated by commas, for example Coins:4000 or Coins:2000,BlackCore:1."); targetPrefabs = BindConfig("General", "Target prefabs", "dvergrprops_crate_long", "Prefab names that should become purchasable, separated by commas."); loggingEnabled = BindConfig("General", "Enable logging", defaultValue: false, "Enable logging for interaction events.", synchronizedSetting: false); requirements.SettingChanged += delegate { BuyAndDestroy.UpdateDescription(); }; targetPrefabs.SettingChanged += delegate { ApplyConfiguredPrefabs(ZNetScene.instance); }; } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); instance = null; harmony.UnpatchSelf(); } public static void LogInfo(object data) { if (loggingEnabled.Value) { ((BaseUnityPlugin)instance).Logger.LogInfo(data); } } public static void LogWarning(object data) { ((BaseUnityPlugin)instance).Logger.LogWarning(data); } private ConfigEntry BindConfig(string group, string name, T defaultValue, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry val = ((BaseUnityPlugin)this).Config.Bind(group, name, defaultValue, description); SyncedConfigEntry val2 = ((ConditionalConfigSync)configSync).AddConfigEntry(val); ((OwnConfigEntryBase)val2).SynchronizedConfig = synchronizedSetting; return val; } private ConfigEntry BindConfig(string group, string name, T defaultValue, string description, bool synchronizedSetting = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return BindConfig(group, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty()), synchronizedSetting); } private static IEnumerable GetTargetPrefabNames() { HashSet hashSet = new HashSet(StringComparer.Ordinal); string text = ((targetPrefabs != null) ? targetPrefabs.Value : "dvergrprops_crate_long"); string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { string text3 = text2.Trim(); if (!string.IsNullOrEmpty(text3)) { hashSet.Add(text3); } } return hashSet; } internal static void ApplyConfiguredPrefabs(ZNetScene scene) { if ((Object)(object)scene == (Object)null) { return; } HashSet hashSet = new HashSet(GetTargetPrefabNames(), StringComparer.Ordinal); foreach (string item in new List(managedPrefabTexts.Keys)) { if (!hashSet.Contains(item)) { GameObject prefab = scene.GetPrefab(item); BuyAndDestroy buyAndDestroy = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent() : null); if ((Object)(object)buyAndDestroy != (Object)null) { HoverText val = prefab.GetComponent() ?? prefab.AddComponent(); val.m_text = managedPrefabTexts[item]; Object.Destroy((Object)(object)buyAndDestroy); } managedPrefabTexts.Remove(item); } } foreach (string item2 in hashSet) { GameObject prefab2 = scene.GetPrefab(item2); if ((Object)(object)prefab2 == (Object)null) { if ((Object)(object)instance != (Object)null) { LogWarning("Target prefab was not found: " + item2); } continue; } BuyAndDestroy component = prefab2.GetComponent(); if ((Object)(object)component != (Object)null) { managedPrefabTexts[item2] = component.m_text; continue; } HoverText component2 = prefab2.GetComponent(); if ((Object)(object)component2 == (Object)null) { if ((Object)(object)instance != (Object)null) { LogWarning("Target prefab does not have HoverText and cannot be made purchasable: " + item2); } } else { managedPrefabTexts[item2] = component2.m_text; BuyAndDestroy buyAndDestroy2 = prefab2.AddComponent(); buyAndDestroy2.m_text = component2.m_text; Object.Destroy((Object)(object)component2); } } } } internal sealed class DvergrPaidItemStorage : MonoBehaviour { [HarmonyPatch(typeof(Character), "Awake")] private static class CharacterAwakePatch { private static void Postfix(Character __instance) { if (IsDvergr(__instance) && (Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] private static class CharacterDropGenerateDropListPatch { private static void Postfix(CharacterDrop __instance) { DropPaidItems(__instance); } } private static readonly int PaidItemsZdoKey = StringExtensionMethods.GetStableHashCode("shudnal.BuyExtractorNeedle.PaidItems"); private const string AcceptPurchaseRpc = "BEN_AcceptPurchase"; private const string StorePaymentRpc = "BEN_StorePayment"; private const string PlayResponseRpc = "BEN_PlayResponse"; private NpcTalk npcTalk; internal ZNetView nview; private bool initialized; private void Awake() { Initialize(); } private bool Initialize() { if (initialized) { return true; } Character component = ((Component)this).GetComponent(); npcTalk = ((Component)this).GetComponent(); nview = ((Component)this).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)npcTalk == (Object)null || (Object)(object)nview == (Object)null || nview.GetZDO() == null) { return false; } nview.Register("BEN_AcceptPurchase", (Action)RPC_AcceptPurchase); nview.Register("BEN_StorePayment", (Action)RPC_StorePayment); nview.Register("BEN_PlayResponse", (Action)RPC_PlayResponse); initialized = true; return true; } internal bool AcceptPurchase(BuyAndDestroy.PurchaseData purchase) { if (!Initialize() || !nview.IsValid() || purchase == null) { return false; } nview.InvokeRPC("BEN_AcceptPurchase", new object[1] { BuyAndDestroy.CreatePurchasePackage(purchase.BuyerName, purchase.PurchasedPrefabName, purchase.Payment) }); return true; } private bool StorePayment(BuyAndDestroy.PurchaseData purchase) { if (!Initialize() || !nview.IsValid() || purchase == null) { return false; } nview.InvokeRPC("BEN_StorePayment", new object[1] { BuyAndDestroy.CreatePurchasePackage(purchase.BuyerName, purchase.PurchasedPrefabName, purchase.Payment) }); return true; } private void RPC_AcceptPurchase(long sender, ZPackage package) { if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { BuyAndDestroy.PurchaseData purchase = BuyAndDestroy.ReadPurchasePackage(package); DistributeAndStorePayment(purchase, 30f); int num = Random.Range(0, BuyAndDestroy.s_randomBuy.Count); nview.InvokeRPC(ZRoutedRpc.Everybody, "BEN_PlayResponse", new object[1] { num }); } } private void RPC_StorePayment(long sender, ZPackage package) { if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner()) { BuyAndDestroy.PurchaseData purchaseData = BuyAndDestroy.ReadPurchasePackage(package); StoreItems(purchaseData.Payment, purchaseData); } } private void RPC_PlayResponse(long sender, int lineIndex) { BuyAndDestroy.PlaySaleResponse(npcTalk, lineIndex); } private void DistributeAndStorePayment(BuyAndDestroy.PurchaseData purchase, float radius) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) List list = ClonePayment(purchase.Payment); List list2 = FindNearby(((Component)this).transform.position, radius, this); List list3 = new List(); int num = 0; foreach (BuyAndDestroy.PaymentItem item in list) { int maxStackSize = GetMaxStackSize(item.PrefabName); while (item.Amount > maxStackSize && num < list2.Count) { DvergrPaidItemStorage dvergrPaidItemStorage = list2[num++]; List payment = new List { item.Clone(maxStackSize) }; BuyAndDestroy.PurchaseData purchase2 = new BuyAndDestroy.PurchaseData(purchase.BuyerName, purchase.PurchasedPrefabName, payment); if (dvergrPaidItemStorage.StorePayment(purchase2)) { item.Amount -= maxStackSize; list3.Add(dvergrPaidItemStorage.GetLogDescription() + " <- " + BuyAndDestroy.FormatPayment(payment)); } else if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Could not assign " + BuyAndDestroy.FormatPayment(payment) + " from player '" + purchase.BuyerName + "' to " + dvergrPaidItemStorage.GetLogDescription() + ". The main Dvergr will keep it instead."); } } } StoreItems(list, purchase); list3.Insert(0, GetLogDescription() + " <- " + BuyAndDestroy.FormatPayment(list)); if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo("Payment distribution for player '" + purchase.BuyerName + "' buying '" + purchase.PurchasedPrefabName + "': " + string.Join("; ", list3.ToArray()) + "."); } } private void StoreItems(IEnumerable payment, BuyAndDestroy.PurchaseData purchase) { ZDO val = (((Object)(object)nview != (Object)null) ? nview.GetZDO() : null); if (val == null) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Could not store payment on " + GetLogDescription() + " because its ZDO is unavailable."); } return; } List list = ClonePayment(payment); Dictionary dictionary = ReadStoredItems(val); foreach (BuyAndDestroy.PaymentItem item in list) { dictionary.TryGetValue(item.PrefabName, out var value); dictionary[item.PrefabName] = (int)Math.Min(2147483647L, (long)value + (long)item.Amount); } WriteStoredItems(val, dictionary); if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo("Stored payment from player '" + purchase.BuyerName + "' for '" + purchase.PurchasedPrefabName + "' on " + GetLogDescription() + ": added " + BuyAndDestroy.FormatPayment(list) + "; total stored " + FormatStoredItems(dictionary) + "."); } } private static List ClonePayment(IEnumerable payment) { List list = new List(); if (payment == null) { return list; } foreach (BuyAndDestroy.PaymentItem item in payment) { if (item != null && item.Amount > 0) { list.Add(item.Clone(item.Amount)); } } return list; } private static int GetMaxStackSize(string prefabName) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); return ((Object)(object)val2 != (Object)null && val2.m_itemData != null && val2.m_itemData.m_shared != null) ? Math.Max(1, val2.m_itemData.m_shared.m_maxStackSize) : int.MaxValue; } internal static DvergrPaidItemStorage FindClosest(Vector3 position, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) List list = FindNearby(position, radius, null); return (list.Count > 0) ? list[0] : null; } private static List FindNearby(Vector3 position, float radius, DvergrPaidItemStorage excluded) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Character.GetCharactersInRange(position, radius, list); List list2 = new List(); foreach (Character item in list) { if (IsDvergr(item)) { DvergrPaidItemStorage dvergrPaidItemStorage = ((Component)item).GetComponent(); if ((Object)(object)dvergrPaidItemStorage == (Object)null) { dvergrPaidItemStorage = ((Component)item).gameObject.AddComponent(); } if (!((Object)(object)dvergrPaidItemStorage == (Object)(object)excluded) && dvergrPaidItemStorage.Initialize() && dvergrPaidItemStorage.nview.IsValid()) { list2.Add(dvergrPaidItemStorage); } } } list2.Sort(delegate(DvergrPaidItemStorage left, DvergrPaidItemStorage right) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)left).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)right).transform.position - position; float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude; return sqrMagnitude.CompareTo(sqrMagnitude2); }); return list2; } internal static bool IsDvergr(Character candidate) { if ((Object)(object)candidate == (Object)null || (Object)(object)((Component)candidate).GetComponent() == (Object)null) { return false; } ZNetView component = ((Component)candidate).GetComponent(); if ((Object)(object)component == (Object)null || component.GetZDO() == null) { return false; } string prefabName = component.GetPrefabName(); return !string.IsNullOrEmpty(prefabName) && prefabName.StartsWith("Dverger", StringComparison.Ordinal); } internal string GetLogDescription() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) string text = (((Object)(object)nview != (Object)null) ? nview.GetPrefabName() : ((Object)((Component)this).gameObject).name); if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)this).gameObject).name; } string text2 = text; Vector3 position = ((Component)this).transform.position; return "'" + text2 + "' at " + ((Vector3)(ref position)).ToString("F1"); } private static string GetLogDescription(Character character, ZNetView characterView) { //IL_0066: 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_006b: Unknown result type (might be due to invalid IL or missing references) string text = (((Object)(object)characterView != (Object)null) ? characterView.GetPrefabName() : (((Object)(object)character != (Object)null) ? ((Object)((Component)character).gameObject).name : "Unknown Dvergr")); if (string.IsNullOrEmpty(text) && (Object)(object)character != (Object)null) { text = ((Object)((Component)character).gameObject).name; } Vector3 val = (((Object)(object)character != (Object)null) ? ((Component)character).transform.position : Vector3.zero); return "'" + text + "' at " + ((Vector3)(ref val)).ToString("F1"); } private static Dictionary ReadStoredItems(ZDO zdo) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); if (zdo == null) { return dictionary; } string text = zdo.GetString(PaidItemsZdoKey, ""); if (string.IsNullOrEmpty(text)) { return dictionary; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { int num = text2.LastIndexOf(':'); if (num > 0 && num < text2.Length - 1) { string key = text2.Substring(0, num); if (int.TryParse(text2.Substring(num + 1), out var result) && result > 0) { dictionary.TryGetValue(key, out var value); dictionary[key] = (int)Math.Min(2147483647L, (long)value + (long)result); } } } return dictionary; } private static void WriteStoredItems(ZDO zdo, Dictionary items) { if (zdo == null) { return; } List list = new List(); foreach (KeyValuePair item in items) { if (!string.IsNullOrEmpty(item.Key) && item.Value > 0) { list.Add(item.Key + ":" + item.Value); } } list.Sort(StringComparer.Ordinal); zdo.Set(PaidItemsZdoKey, string.Join(";", list.ToArray())); } private static string FormatStoredItems(IDictionary items) { if (items == null || items.Count == 0) { return "nothing"; } return string.Join(", ", (from item in items.Where((KeyValuePair item) => !string.IsNullOrEmpty(item.Key) && item.Value > 0).OrderBy, string>((KeyValuePair item) => item.Key, StringComparer.Ordinal) select item.Key + " x" + item.Value).ToArray()); } private static void DropPaidItems(CharacterDrop characterDrop) { //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) Character val = (((Object)(object)characterDrop != (Object)null) ? ((Component)characterDrop).GetComponent() : null); if ((Object)(object)val == (Object)null && (Object)(object)characterDrop != (Object)null) { val = ((Component)characterDrop).GetComponentInParent(); } if ((Object)(object)val == (Object)null) { return; } ZNetView component = ((Component)val).GetComponent(); ZDO val2 = (((Object)(object)component != (Object)null) ? component.GetZDO() : null); string text = ((val2 != null) ? val2.GetString(PaidItemsZdoKey, "") : ""); if (string.IsNullOrEmpty(text)) { return; } string logDescription = GetLogDescription(val, component); if (!IsDvergr(val)) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning(logDescription + " has stored payment but was not recognized as a Dvergr at death. Raw stored value: " + text + "."); } return; } if ((Object)(object)component == (Object)null || !component.IsValid()) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning(logDescription + " died with stored payment, but its ZNetView was not valid. Raw stored value: " + text + "."); } return; } if (!component.IsOwner()) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo("Stored payment drop for " + logDescription + " was skipped on this peer because it is not the ZDO owner. Raw stored value: " + text + "."); } return; } Dictionary dictionary = ReadStoredItems(val2); if (dictionary.Count == 0) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning(logDescription + " died with an unreadable stored payment value: " + text + "."); } return; } if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogInfo(logDescription + " died with stored payment: " + FormatStoredItems(dictionary) + "."); } Dictionary dictionary2 = new Dictionary(StringComparer.Ordinal); int num = 0; foreach (KeyValuePair item in dictionary) { GameObject val3 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item.Key) : null); ItemDrop val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent() : null); if ((Object)(object)val4 == (Object)null || val4.m_itemData == null || val4.m_itemData.m_shared == null) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Cannot drop stored payment from " + logDescription + " because item prefab was not found: " + item.Key + " x" + item.Value + "."); } continue; } int val5 = Math.Max(1, val4.m_itemData.m_shared.m_maxStackSize); int num2 = item.Value; while (num2 > 0) { int num3 = Math.Min(val5, num2); Vector3 position = ((Component)val).transform.position + Vector3.up + Random.insideUnitSphere * 0.4f; ItemDrop val6; try { val6 = BuyAndDestroy.DropItemStack(val3, val4, num3, position, Random.rotation); } catch (Exception ex) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Failed to drop " + item.Key + " x" + num3 + " from " + logDescription + ": " + ex?.ToString() + "."); } break; } if ((Object)(object)val6 == (Object)null) { if ((Object)(object)BuyExtractorNeedle.instance != (Object)null) { BuyExtractorNeedle.LogWarning("Failed to create dropped item " + item.Key + " x" + num3 + " for " + logDescription + "."); } break; } dictionary2.TryGetValue(item.Key, out var value); dictionary2[item.Key] = value + num3; num++; num2 -= num3; } } val2.Set(PaidItemsZdoKey, ""); if (!((Object)(object)BuyExtractorNeedle.instance == (Object)null)) { int num4 = dictionary.Sum((KeyValuePair item) => item.Value); int num5 = dictionary2.Sum((KeyValuePair item) => item.Value); if (num5 == num4) { BuyExtractorNeedle.LogInfo(logDescription + " dropped stored payment: " + FormatStoredItems(dictionary2) + " in " + num + " stack(s)."); } else { BuyExtractorNeedle.LogWarning(logDescription + " dropped only " + FormatStoredItems(dictionary2) + " in " + num + " stack(s); expected " + FormatStoredItems(dictionary) + "."); } } } } }