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 Computer AutoLootbag v0.0.27
Computer-AutoLootbag.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ComputerMods.ConfigSync; using HarmonyLib; using Jotunn; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Computer-AutoLootbag")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.0.27.0")] [assembly: AssemblyInformationalVersion("0.0.27")] [assembly: AssemblyProduct("Computer-AutoLootbag")] [assembly: AssemblyTitle("Computer-AutoLootbag")] [assembly: AssemblyVersion("0.0.27.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 ComputerMods.ConfigSync { internal sealed class ServerConfigSync : IDisposable { private static readonly List<ServerConfigSync> instances = new List<ServerConfigSync>(); private static Harmony? hooks; private readonly ConfigFile config; private readonly string guid; private readonly Dictionary<ConfigEntryBase, ConfigurationManagerAttributes> gameplay = new Dictionary<ConfigEntryBase, ConfigurationManagerAttributes>(); private readonly Dictionary<ConfigEntryBase, object> local = new Dictionary<ConfigEntryBase, object>(); private readonly Dictionary<ConfigEntryBase, object> remote = new Dictionary<ConfigEntryBase, object>(); private readonly Dictionary<ConfigurationManagerAttributes, (bool Admin, bool? ReadOnly, bool? HideDefault)> originalTags = new Dictionary<ConfigurationManagerAttributes, (bool, bool?, bool?)>(); private bool client; private bool ready; private bool receiving; private bool writing; private bool leaving; private bool disposed; private bool remoteEnabled = true; public const float PushDelay = 0.5f; private static MethodInfo? pushMethod; private static bool pushChecked; private static bool pushMissingLogged; private static bool pushPending; private static float pushDue; internal static Func<float> Clock = () => Time.realtimeSinceStartup; public ConfigEntry<bool> Enabled { get; } public bool IsServerControlled { get { if (client) { if (ready) { return remoteEnabled; } return true; } return false; } } private static bool PlayerIsAdmin => SynchronizationManager.Instance.PlayerIsAdmin; public event Action? Applied; private static MethodInfo? FindPush() { if (pushChecked) { return pushMethod; } pushChecked = true; pushMethod = AccessTools.Method(typeof(SynchronizationManager), "SynchronizeChangedConfig", (Type[])null, (Type[])null); if (pushMethod == null) { Logger.LogWarning((object)"ServerConfigSync: Jotunn's config push (SynchronizeChangedConfig) was not found; in-game admin edits sync when the config window closes."); } return pushMethod; } public static ServerConfigSync Attach(BaseUnityPlugin plugin) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_00f8: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown ServerConfigSync serverConfigSync = new ServerConfigSync(plugin.Config, plugin.Info.Metadata.GUID); FindPush(); bool flag = false; try { if (hooks == null) { hooks = new Harmony(plugin.Info.Metadata.GUID + ".computer-config-sync"); flag = true; hooks.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "Start", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerConfigSync), "BeforeStart", (Type[])null) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); hooks.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "OnDestroy", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerConfigSync), "BeforeDestroy", (Type[])null) { priority = 800 }, new HarmonyMethod(typeof(ServerConfigSync), "AfterDestroy", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); hooks.Patch((MethodBase)AccessTools.Method(typeof(ConfigEntryBase), "GetSerializedValue", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerConfigSync), "AfterSerialize", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); hooks.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerConfigSync), "AfterNetUpdate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } return serverConfigSync; } catch { if (flag) { Harmony? obj2 = hooks; if (obj2 != null) { obj2.UnpatchSelf(); } hooks = null; } serverConfigSync.Dispose(); throw; } } internal ServerConfigSync(ConfigFile config, string guid) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown if (instances.Any((ServerConfigSync p) => p.config == config)) { throw new InvalidOperationException("Config already has a server sync policy."); } this.config = config; this.guid = guid; Enabled = config.Bind<bool>("ServerSync", "Enabled", true, new ConfigDescription("Server-owned policy. True enforces server gameplay settings; false lets each player use local gameplay settings. Change on the host/server and reload its config. Client values cannot override the server policy.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); Refresh(); RememberTags(Tags((ConfigEntryBase)(object)Enabled)); config.SettingChanged += EntryChanged; instances.Add(this); SynchronizationManager.OnSyncingConfiguration += BeforeSync; SynchronizationManager.OnConfigurationSynchronized += AfterSync; SynchronizationManager.OnAdminStatusChanged += AdminChanged; } public void Refresh() { if (client) { throw new InvalidOperationException("Bind gameplay settings before connecting."); } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config) { ConfigEntryBase value = item.Value; if ((object)value != Enabled && !gameplay.ContainsKey(value)) { ConfigurationManagerAttributes val = Tags(value); if (val != null && val.IsAdminOnly) { gameplay.Add(value, val); RememberTags(val); } } } } internal void BeginSession(bool isClient) { client = isClient; ready = false; receiving = false; leaving = false; local.Clear(); remote.Clear(); remoteEnabled = true; foreach (ConfigEntryBase key in gameplay.Keys) { local[key] = key.BoxedValue; } local[(ConfigEntryBase)(object)Enabled] = ((ConfigEntryBase)Enabled).BoxedValue; SetTags(synchronizeGameplay: true); } private void BeforeSync(object? sender, SyncingConfigurationEventArgs args) { if (!client || leaving) { return; } receiving = true; if (ready && !remoteEnabled) { foreach (ConfigEntryBase key in gameplay.Keys) { local[key] = key.BoxedValue; } } SetTags(synchronizeGameplay: true); Write(delegate { if (ready) { Enabled.Value = remoteEnabled; foreach (KeyValuePair<ConfigEntryBase, object> item in remote) { item.Key.BoxedValue = item.Value; } } }); } private void AfterSync(object? sender, ConfigurationSynchronizationEventArgs args) { if (!client) { if (args.UpdatedPluginGUIDs.Contains(guid)) { Notify(); } } else { if (!receiving || leaving) { return; } if (!args.UpdatedPluginGUIDs.Contains(guid)) { if (ready) { if (!remoteEnabled) { Write(delegate { foreach (ConfigEntryBase key in gameplay.Keys) { key.BoxedValue = local[key]; } }); } SetTags(remoteEnabled); } receiving = false; return; } remoteEnabled = Enabled.Value; foreach (ConfigEntryBase key2 in gameplay.Keys) { remote[key2] = key2.BoxedValue; } ready = true; if (!remoteEnabled) { Write(delegate { foreach (ConfigEntryBase key3 in gameplay.Keys) { key3.BoxedValue = local[key3]; } }); } SetTags(remoteEnabled); receiving = false; Notify(); } } private void EntryChanged(object? sender, SettingChangedEventArgs args) { if (writing || leaving || receiving) { return; } ConfigEntryBase entry = args.ChangedSetting; if ((object)entry != Enabled && !gameplay.ContainsKey(entry)) { return; } if (client) { if (!ready) { return; } if ((object)entry == Enabled) { Write(delegate { Enabled.Value = remoteEnabled; }); } else if (remoteEnabled && PlayerIsAdmin) { remote[entry] = entry.BoxedValue; SchedulePush(); } else if (remoteEnabled) { Write(delegate { entry.BoxedValue = remote[entry]; }); } else { local[entry] = entry.BoxedValue; } } Notify(); } private void AdminChanged() { if (client && ready && !leaving) { SetTags(remoteEnabled); } } private void SetTags(bool synchronizeGameplay) { foreach (KeyValuePair<ConfigEntryBase, ConfigurationManagerAttributes> item in gameplay) { item.Value.IsAdminOnly = !client || synchronizeGameplay; if (client) { item.Value.ReadOnly = synchronizeGameplay && !PlayerIsAdmin; } } ConfigurationManagerAttributes val = Tags((ConfigEntryBase)(object)Enabled); val.IsAdminOnly = true; if (client) { val.ReadOnly = true; } } private static ConfigurationManagerAttributes? Tags(ConfigEntryBase entry) { return entry.Description.Tags.OfType<ConfigurationManagerAttributes>().FirstOrDefault(); } private void RememberTags(ConfigurationManagerAttributes tag) { if (!originalTags.ContainsKey(tag)) { originalTags.Add(tag, (tag.IsAdminOnly, tag.ReadOnly, tag.HideDefaultButton)); } } private void RestoreTags() { foreach (KeyValuePair<ConfigurationManagerAttributes, (bool, bool?, bool?)> originalTag in originalTags) { originalTag.Key.IsAdminOnly = originalTag.Value.Item1; originalTag.Key.ReadOnly = originalTag.Value.Item2; originalTag.Key.HideDefaultButton = originalTag.Value.Item3; } } private void Write(Action action) { bool flag = writing; bool saveOnConfigSet = config.SaveOnConfigSet; writing = true; config.SaveOnConfigSet = false; try { action(); } finally { config.SaveOnConfigSet = saveOnConfigSet; writing = flag; } } internal void BeginDisconnect() { pushPending = false; if (!client) { return; } if (ready && !remoteEnabled) { foreach (ConfigEntryBase key in gameplay.Keys) { local[key] = key.BoxedValue; } } leaving = true; SetTags(synchronizeGameplay: true); } internal void EndDisconnect() { if (client) { Write(delegate { foreach (KeyValuePair<ConfigEntryBase, object> item in local) { item.Key.BoxedValue = item.Value; } }); } client = false; ready = false; leaving = false; receiving = false; RestoreTags(); local.Clear(); remote.Clear(); Notify(); } internal string SerializeLocal(ConfigEntryBase entry, string original) { if (!client || !local.TryGetValue(entry, out object value)) { return original; } if (ready && !remoteEnabled && !receiving && !writing && !leaving && (object)entry != Enabled) { value = entry.BoxedValue; } return TomlTypeConverter.ConvertToString(value, entry.SettingType); } public static bool PushAdminChanges() { pushPending = false; if (!PlayerIsAdmin || !instances.Any((ServerConfigSync p) => p.client && p.ready && !p.leaving)) { return false; } try { MethodInfo methodInfo = FindPush(); if (methodInfo == null) { if (!pushMissingLogged) { pushMissingLogged = true; Logger.LogError((object)"ServerConfigSync: Jotunn config push not found; admin edits stay local until the config window closes."); } return false; } methodInfo.Invoke(SynchronizationManager.Instance, null); return true; } catch (Exception ex) { Logger.LogError((object)("ServerConfigSync admin push failed: " + ex)); return false; } } private static void SchedulePush() { pushPending = true; pushDue = Clock() + 0.5f; } internal static void AfterNetUpdate() { if (pushPending && Clock() >= pushDue) { PushAdminChanges(); } } private void Notify() { if (this.Applied == null) { return; } Delegate[] invocationList = this.Applied.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action action = (Action)invocationList[i]; try { action(); } catch (Exception ex) { Logger.LogError((object)("ServerConfigSync apply callback failed for " + guid + " (" + (action.Method.DeclaringType?.FullName ?? "?") + "): " + ex)); } } } private static void BeforeStart(ZNet __instance) { ServerConfigSync[] array = instances.ToArray(); for (int i = 0; i < array.Length; i++) { array[i].BeginSession(!__instance.IsServer()); } } private static void BeforeDestroy() { ServerConfigSync[] array = instances.ToArray(); for (int i = 0; i < array.Length; i++) { array[i].BeginDisconnect(); } } private static void AfterDestroy() { ServerConfigSync[] array = instances.ToArray(); for (int i = 0; i < array.Length; i++) { array[i].EndDisconnect(); } } private static void AfterSerialize(ConfigEntryBase __instance, ref string __result) { foreach (ServerConfigSync instance in instances) { __result = instance.SerializeLocal(__instance, __result); } } public void Dispose() { if (disposed) { return; } BeginDisconnect(); EndDisconnect(); disposed = true; config.SettingChanged -= EntryChanged; SynchronizationManager.OnSyncingConfiguration -= BeforeSync; SynchronizationManager.OnConfigurationSynchronized -= AfterSync; SynchronizationManager.OnAdminStatusChanged -= AdminChanged; instances.Remove(this); if (instances.Count == 0) { Harmony? obj = hooks; if (obj != null) { obj.UnpatchSelf(); } hooks = null; } } } } namespace Computer.AutoLootbag { internal static class AzothAction { internal static string Refusal(bool available, bool selected, bool known, bool busy, bool deleting, int held, int shownAmount, int shownAzoth, int freshAmount, int freshAzoth, string providerReason) { if (busy) { return "An Azoth conversion is already running."; } if (deleting) { return "Finish or cancel the delete question first."; } if (!available) { if (!string.IsNullOrEmpty(providerReason)) { return providerReason; } return "Azoth conversion is unavailable on this server."; } if (!selected) { return "Select an item's name in the bag first. Only that row is converted."; } if (!known) { return "This item's mod is not loaded. Its loot stays in the bag."; } if (held <= 0 || shownAmount > held) { return "The selected loot changed. Select it again; nothing was used."; } if (freshAmount <= 0 || freshAzoth <= 0) { if (!string.IsNullOrEmpty(providerReason)) { return providerReason; } return "Alchemy won't accept this item or quantity under the current rates and batch limits."; } if (freshAmount > held || freshAmount != shownAmount || freshAzoth != shownAzoth) { return "The Alchemy quote changed. Check the new amount and click again; nothing was used."; } return ""; } } internal readonly struct AzothQuote { internal readonly int Amount; internal readonly int Azoth; internal readonly string Reason; internal AzothQuote(int amount, int azoth, string reason = "") { Amount = amount; Azoth = azoth; Reason = reason; } } internal sealed class AzothBatch { internal delegate bool Pay(string name, int amount, int expectedAzoth, Func<bool> consume, Action<bool, int, float, string> done); private readonly Func<BagModel?> read; private readonly Func<BagModel, BagModel, bool> replace; private readonly Func<string, int, AzothQuote> quote; private readonly Pay pay; private readonly Action<string, int, int, BagModel>? intent; private readonly Queue<KeyValuePair<string, int>> rows; private BagModel? expected; private int expectedRevision; private int remaining; private int batchIndex; private readonly AzothPlan? approved; private string item = ""; private bool stepping; private bool paying; private bool stopped; private readonly HashSet<string> used = new HashSet<string>(StringComparer.Ordinal); internal bool Done { get; private set; } internal long Pieces { get; private set; } internal long Azoth { get; private set; } internal float Xp { get; private set; } internal int Skipped { get; private set; } internal string Reason { get; private set; } = ""; internal bool Uncertain { get; private set; } internal string Warning { get; private set; } = ""; internal string Summary { get { if (Pieces <= 0) { if (Reason.Length <= 0) { return "Nothing eligible in your active lootbag. Whole-batch leftovers and excluded items were kept."; } return "Nothing converted. " + Reason; } return "Converted " + Pieces.ToString("N0", CultureInfo.InvariantCulture) + " items (" + used.Count + " kinds) into " + Azoth.ToString("N0", CultureInfo.InvariantCulture) + " Azoth" + ((Xp > 0f) ? (" (+" + Xp.ToString("0.##", CultureInfo.InvariantCulture) + " Alchemy XP)") : "") + ". " + (stopped ? ("Stopped: " + Reason) : ((Skipped > 0) ? (Skipped + " ineligible/leftover rows kept. " + Reason) : "")) + ((Warning.Length > 0) ? (" Warning: " + Warning) : ""); } } internal AzothBatch(Func<BagModel?> read, Func<BagModel, BagModel, bool> replace, Func<string, int, AzothQuote> quote, Pay pay, string? selected = null, Action<string, int, int, BagModel>? intent = null, AzothPlan? approved = null) { this.read = read; this.replace = replace; this.quote = quote; this.pay = pay; this.intent = intent; this.approved = approved; expected = read(); expectedRevision = expected?.Revision ?? 0; IEnumerable<KeyValuePair<string, int>> collection; if (expected != null) { collection = from i in expected.Items.Values.Where((BagItem i) => selected == null || i.Name == selected).OrderBy<BagItem, string>((BagItem i) => i.Name, StringComparer.Ordinal) select new KeyValuePair<string, int>(i.Name, i.Total); } else { IEnumerable<KeyValuePair<string, int>> enumerable = Array.Empty<KeyValuePair<string, int>>(); collection = enumerable; } rows = new Queue<KeyValuePair<string, int>>(collection); } internal void Step() { if (Done || stepping) { return; } stepping = true; BagModel live; string frozen; BagModel staged; bool consumed; bool answered; try { if (expected == null || expected != read() || expected.Revision != expectedRevision) { Stop("The active bag changed. Remaining loot was kept; click again after checking it."); return; } if (remaining <= 0) { if (rows.Count == 0) { Done = true; return; } KeyValuePair<string, int> keyValuePair = rows.Dequeue(); item = keyValuePair.Key; remaining = keyValuePair.Value; batchIndex = 0; } live = expected; frozen = live.Serialize(); int num = Math.Min(remaining, live.Count(item)); AzothQuote offered = quote(item, num); if (approved != null) { bool num2 = offered.Amount > 0 && offered.Azoth > 0; AzothPlan.Row value; bool flag = approved.Rows.TryGetValue(item, out value) && batchIndex < value.Batches.Count; if ((num2 || flag) && !approved.Matches(item, num, batchIndex, offered)) { Stop("The displayed Azoth quote changed. Remaining loot was kept; check the refreshed amounts."); return; } } if (offered.Amount <= 0 || offered.Azoth <= 0) { Skipped++; remaining = 0; if (Reason.Length == 0) { Reason = offered.Reason; } return; } if (offered.Amount > num) { Stop("Alchemy returned an invalid quantity. Nothing further was used."); return; } if (!BagModel.TryParse(frozen, out staged) || staged.Take(item, offered.Amount) != offered.Amount) { Stop("The selected loot changed. Nothing further was used."); return; } staged.Revision = live.Revision + 1; string text = staged.Serialize(); consumed = false; answered = false; bool accepted = false; int paid = 0; float xp = 0f; string message = ""; intent?.Invoke(item, offered.Amount, offered.Azoth, live); paying = true; bool num3 = pay(item, offered.Amount, offered.Azoth, Consume, delegate(bool ok, int got, float earned, string why) { if (!answered) { answered = true; accepted = ok; paid = got; xp = earned; message = why ?? ""; } }); paying = false; if (!num3 || !answered || accepted != consumed || (accepted && paid != offered.Azoth)) { Uncertain = true; Stop("Alchemy did not confirm a safe exchange. Conversion stopped; do not retry until its result is checked."); return; } if (message.StartsWith("UNCERTAIN:", StringComparison.Ordinal)) { Uncertain = true; Stop(message); return; } if (!accepted) { Stop((message.Length > 0) ? message : "Alchemy refused the exchange. Remaining loot was kept."); return; } Pieces += offered.Amount; Azoth += paid; if (xp > 0f && !float.IsNaN(xp) && !float.IsInfinity(xp)) { Xp += xp; } if (message.Length > 0) { Warning = message; } used.Add(item); remaining -= offered.Amount; batchIndex++; if (read() != staged || staged.Serialize() != text) { Stop("Your bag changed after a committed exchange. Earlier results are kept; remaining rows were not retried."); return; } expected = read(); expectedRevision = expected?.Revision ?? 0; } catch (Exception ex) { Uncertain |= paying; Stop("Alchemy conversion failed: " + ex.Message + ". Conversion stopped; no automatic retry."); } finally { stepping = false; } bool Consume() { if (consumed || answered || live != read() || live.Serialize() != frozen) { return false; } consumed = replace(live, staged); return consumed; } } private void Stop(string why) { Reason = why; Done = true; stopped = true; } } internal static class BagStore { internal const string AzothIntentKey = "ComputerAutoLootbag.azoth.v1"; private static Player? azothOperationPlayer; private static string azothInitial = ""; internal const string SaveKey = "ComputerAutoLootbag.v1"; internal const string LeftKey = "ComputerAutoLootbag.left.v1"; internal const string InventoryFull = "Inventory full"; private static BagModel? bag; private static long owner; private static readonly List<Gone> gone = new List<Gone>(); private static readonly List<KeyValuePair<string, int>> gains = new List<KeyValuePair<string, int>>(); private static readonly List<KeyValuePair<string, int>> spilled = new List<KeyValuePair<string, int>>(); private static readonly List<KeyValuePair<string, int>> lines = new List<KeyValuePair<string, int>>(); private static readonly Dictionary<string, long> announced = new Dictionary<string, long>(StringComparer.Ordinal); private static float nextSweep; private static float nextGains; private static float nextSpot; private static List<LeftBag> left = new List<LeftBag>(); internal static int LeftRevision; private static long tombUser; private static uint tombId; private static int tombFrame = -100; internal const string CarryKey = "ComputerAutoLootbag.carry.v1"; private static List<SealedBag> seals = new List<SealedBag>(); private static bool carryReadable = true; internal static IReadOnlyList<LeftBag> Left => left; internal static bool Ready { get { Player localPlayer = Player.m_localPlayer; if (bag != null && Object.op_Implicit((Object)(object)localPlayer)) { return owner == localPlayer.GetPlayerID(); } return false; } } internal static BagModel? Bag { get { if (!Ready) { return null; } return bag; } } internal static IReadOnlyList<SealedBag> Seals { get { if (!Ready) { return Array.Empty<SealedBag>(); } return seals; } } internal static bool BeginAzothOperation(Player player, string? selected, out string why) { why = ""; if (!Ready || (Object)(object)azothOperationPlayer != (Object)null) { why = "Your lootbag is busy or not ready."; return false; } if (player.m_customData.ContainsKey("ComputerAutoLootbag.azoth.v1")) { why = "An earlier Azoth exchange needs inspection. Conversion is held; nothing will be retried automatically."; return false; } string s = bag.Serialize(); azothInitial = "CAAZ1\nowner=" + player.GetPlayerID() + "\nworld=" + ZNet.instance.GetWorldUID() + "\nsource=active bag only\nselection=" + (selected ?? "all eligible") + "\noriginal=" + Convert.ToBase64String(Encoding.UTF8.GetBytes(s)) + "\n"; player.m_customData["ComputerAutoLootbag.azoth.v1"] = azothInitial + "state=started\n"; azothOperationPlayer = player; return true; } internal static void StageAzothIntent(string item, int amount, int value, BagModel original) { Player val = azothOperationPlayer; if (!Ready || !Object.op_Implicit((Object)(object)val) || (Object)(object)val != (Object)(object)Player.m_localPlayer || bag != original) { throw new InvalidOperationException("Original active bag owner changed."); } val.m_customData["ComputerAutoLootbag.azoth.v1"] = azothInitial + "state=pending\nitem=" + item + "\namount=" + amount + "\nexpectedAzoth=" + value + "\nbefore=" + Convert.ToBase64String(Encoding.UTF8.GetBytes(original.Serialize())) + "\n"; } internal static bool CommitAzoth(BagModel expected, BagModel replacement) { Player val = azothOperationPlayer; if (!Ready || !Object.op_Implicit((Object)(object)val) || (Object)(object)val != (Object)(object)Player.m_localPlayer || bag != expected) { return false; } string text = replacement.Serialize(); string value = val.m_customData["ComputerAutoLootbag.azoth.v1"] + "state=source committed\nafter=" + Convert.ToBase64String(Encoding.UTF8.GetBytes(text)) + "\n"; val.m_customData["ComputerAutoLootbag.v1"] = text; val.m_customData["ComputerAutoLootbag.azoth.v1"] = value; bag = replacement; return true; } internal static void EndAzothOperation(Player player, bool uncertain, string result) { if ((Object)(object)player != (Object)(object)azothOperationPlayer) { return; } try { if (uncertain) { player.m_customData["ComputerAutoLootbag.azoth.v1"] = player.m_customData["ComputerAutoLootbag.azoth.v1"] + "state=UNCERTAIN\nresult=" + result.Replace('\n', ' ') + "\n"; } else { player.m_customData.Remove("ComputerAutoLootbag.azoth.v1"); } } finally { azothOperationPlayer = null; azothInitial = ""; } } internal static void Loaded(Player player) { long playerID = player.GetPlayerID(); if (playerID == 0L || (bag != null && owner == playerID)) { return; } player.m_customData.TryGetValue("ComputerAutoLootbag.v1", out var value); if (!BagModel.TryParse(value, out BagModel model)) { if (!player.m_customData.ContainsKey("ComputerAutoLootbag.v1.unreadable")) { player.m_customData["ComputerAutoLootbag.v1.unreadable"] = value ?? ""; } Plugin.Log.LogError((object)"Computer Auto Lootbag: the saved loot bag of this character could not be read. It was kept under 'ComputerAutoLootbag.v1.unreadable' and a new bag was started."); } bag = model; owner = playerID; LoadCarry(player); LootNet.Load(player); OverflowStorage.LoadPending(player); announced.Clear(); gains.Clear(); spilled.Clear(); player.m_customData.TryGetValue("ComputerAutoLootbag.left.v1", out var value2); if (!LeftBags.TryParse(value2, out left)) { if (!player.m_customData.ContainsKey("ComputerAutoLootbag.left.v1.unreadable")) { player.m_customData["ComputerAutoLootbag.left.v1.unreadable"] = value2 ?? ""; } Plugin.Log.LogError((object)"Computer Auto Lootbag: the bags this character left at its bodies could not be read. The text was kept under 'ComputerAutoLootbag.left.v1.unreadable'."); } LeftRevision++; if (left.Count > 0) { int num = 0; foreach (LeftBag item in left) { num += item.Bag.Pieces; } Plugin.Diag("left loaded", ("bags", left.Count), ("pieces", num)); } int num2 = 0; foreach (BagItem value3 in model.Items.Values) { num2 += value3.Total; } Plugin.Diag("loaded", ("kinds", model.Items.Count), ("pieces", num2), ("playedMin", (int)(model.Clock / 60.0))); } internal static void Saving(Player player) { if (bag != null && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && owner == player.GetPlayerID()) { player.m_customData["ComputerAutoLootbag.v1"] = bag.Serialize(); SaveCarry(player); LootNet.Save(player); OverflowStorage.SavePending(player); if (left.Count > 0) { player.m_customData["ComputerAutoLootbag.left.v1"] = LeftBags.Serialize(left); } else { player.m_customData.Remove("ComputerAutoLootbag.left.v1"); } } } internal static void TombstoneMade(TombStone stone, long ownerId) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) ZNetView val = default(ZNetView); if (bag != null && ownerId == owner && ((Component)stone).TryGetComponent<ZNetView>(ref val) && val.IsValid()) { ZDOID uid = val.GetZDO().m_uid; tombUser = ((ZDOID)(ref uid)).UserID; tombId = ((ZDOID)(ref uid)).ID; tombFrame = Time.frameCount; } } internal static void Died(Player player) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (Plugin.StayAtBody.Value && bag != null && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && owner == player.GetPlayerID() && bag.Items.Count != 0) { ZNet instance = ZNet.instance; Vector3 position = ((Component)player).transform.position; LeftBag leftBag = new LeftBag { World = (Object.op_Implicit((Object)(object)instance) ? instance.GetWorldUID() : 0), WorldName = (Object.op_Implicit((Object)(object)instance) ? instance.GetWorldName() : ""), X = position.x, Y = position.y, Z = position.z, Bag = bag }; if (Time.frameCount - tombFrame <= 1) { leftBag.TombUser = tombUser; leftBag.TombId = tombId; } tombFrame = -100; left.Add(leftBag); bag = new BagModel { Clock = leftBag.Bag.Clock }; announced.Clear(); gains.Clear(); spilled.Clear(); LeftRevision++; int pieces = leftBag.Bag.Pieces; Plugin.Diag("left", ("pieces", pieces), ("kinds", leftBag.Bag.Items.Count), ("tombstone", leftBag.HasTomb), ("at", ((Vector3)(ref position)).ToString("F0")), ("bagsLeft", left.Count)); Feed.Post("Your loot bag stays at your body: " + LootRules.Number(pieces) + ((pieces == 1) ? " piece" : " pieces")); } } private static void Recover(int index, string by) { if (Ready && carryReadable && index >= 0 && index < left.Count) { LeftBag leftBag = left[index]; SealRules.CollectDeath(bag, leftBag, Mathf.Clamp(Plugin.MaxPerItem.Value, 1, 100000), out BagModel restored, out LeftBag sealedBag); List<LeftBag> list = new List<LeftBag>(left); list.RemoveAt(index); List<SealedBag> list2 = new List<SealedBag>(seals); if (sealedBag != null) { list2.Add(new SealedBag { Token = Guid.NewGuid().ToString("N"), Owner = owner, Carrier = owner, OwnerName = Player.m_localPlayer.GetPlayerName(), CarrierName = Player.m_localPlayer.GetPlayerName(), Escrow = true, Record = sealedBag }); } CommitCarry(restored, list, list2); Plugin.Diag("recovered", ("pieces", leftBag.Bag.Pieces), ("by", by), ("sealed", sealedBag != null), ("bagsLeft", left.Count)); Feed.Post((sealedBag == null) ? "Your Computer Lootbag was recovered." : "Computer Lootbag collected: active bag full. Open J and use Unseal after making room; timers stay paused."); } } private static void CheckSpots(Player player) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < nextSpot) { return; } nextSpot = Time.unscaledTime + 0.5f; if (left.Count == 0 || ((Character)player).IsDead() || CarryNet.OpenCorpse(out Container _, out TombStone _)) { return; } ZNet instance = ZNet.instance; long world = (Object.op_Implicit((Object)(object)instance) ? instance.GetWorldUID() : 0); Vector3 position = ((Component)player).transform.position; for (int i = 0; i < left.Count; i++) { if (LeftBags.AtSpot(left[i], world, position.x, position.y, position.z) && !OwnTombstoneNear(left[i])) { Recover(i, "spot"); break; } } } private static bool OwnTombstoneNear(LeftBag record) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) float num = 64f; TombStone[] array = Object.FindObjectsByType<TombStone>((FindObjectsSortMode)0); ZNetView val2 = default(ZNetView); foreach (TombStone val in array) { if (Object.op_Implicit((Object)(object)val) && ((Component)val).TryGetComponent<ZNetView>(ref val2) && val2.IsValid() && val2.GetZDO().GetLong(ZDOVars.s_owner, 0L) == owner) { Vector3 position = ((Component)val).transform.position; float num2 = position.x - record.X; float num3 = position.z - record.Z; if (num2 * num2 + num3 * num3 <= num) { return true; } } } return false; } internal static void Receive(List<KeyValuePair<string, int>> items, Vector3 at, LootSource source) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) bool flag = Ready && Plugin.UseBag.Value; int cap = Mathf.Clamp(Plugin.MaxPerItem.Value, 1, 100000); int value = Plugin.Minutes.Value; foreach (KeyValuePair<string, int> item in items) { int num = (flag ? bag.Add(item.Key, item.Value, cap, value) : 0); if (num > 0) { Count(gains, item.Key, num); } int num2 = item.Value - num; if (num2 > 0) { Ground.Spawn(item.Key, num2, at); if (flag) { Count(spilled, item.Key, num2); } } } } private static void Count(List<KeyValuePair<string, int>> list, string name, int amount) { for (int i = 0; i < list.Count; i++) { if (list[i].Key == name) { list[i] = new KeyValuePair<string, int>(name, list[i].Value + amount); return; } } list.Add(new KeyValuePair<string, int>(name, amount)); } internal static int TakeOut(string name, int want, out string note) { int num = (Ready ? bag.Count(name) : 0); int num2 = TakeOutCore(name, want, out note); Plugin.Diag("take", ("item", name), ("asked", want), ("inBag", num), ("moved", num2), ("left", Ready ? bag.Count(name) : 0), ("result", (note.Length != 0) ? ((num2 > 0) ? ("partial: " + note) : ("refused: " + note)) : ((num2 > 0) ? "ok" : "nothing"))); return num2; } private static int TakeOutCore(string name, int want, out string note) { note = ""; Player localPlayer = Player.m_localPlayer; if (!Ready || !Object.op_Implicit((Object)(object)localPlayer) || want <= 0) { return 0; } ItemDrop val = RareItems.Find(name); SharedData val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.m_itemData?.m_shared); if (val2 == null) { note = "This item's mod is not installed. It stays in the bag."; return 0; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); int num = Math.Max(1, val2.m_maxStackSize); long room = inventory.FindFreeStackSpace(val2.m_name, (float)Game.m_worldLevel) + (long)inventory.GetEmptySlots() * (long)num; int num2 = Math.Min(want, bag.Count(name)); int num3 = LootRules.Fit(want, bag.Count(name), room); if (num3 <= 0) { note = "Inventory full"; return 0; } int num4 = inventory.CountItems(val2.m_name, -1, true); int num5 = num3; while (num5 > 0) { int num6 = Math.Min(num5, num); if (!inventory.AddItem(((Component)val).gameObject, num6)) { break; } num5 -= num6; } int num7 = Mathf.Clamp(inventory.CountItems(val2.m_name, -1, true) - num4, 0, num3); bag.Take(name, num7); if (num7 < num2) { note = "Inventory full"; } return num7; } internal static void SetUse(bool on, string by) { if (Plugin.UseBag.Value != on) { Plugin.UseBag.Value = on; LootNet.FlagNow(); Plugin.Diag("use", ("state", on ? "on" : "off"), ("by", by)); Feed.Post(on ? "Loot bag on: loot goes into your bag" : "Loot bag off: your share of new loot drops on the ground"); } } internal static int Count(string name) { if (!Ready) { return 0; } return bag.Count(name); } internal static int Delete(string name) { if (!Ready) { return 0; } int num = bag.Take(name, bag.Count(name)); if (num <= 0) { return 0; } announced.Remove(name); Plugin.Diag("deleted", ("item", name), ("pieces", num)); return num; } internal static void Tick(float delta) { LootNet.Register(); Ground.Drain(); LootNet.Tick(); Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || bag == null || owner != localPlayer.GetPlayerID()) { return; } LootNet.PublishFlag(localPlayer); if (!Game.IsPaused()) { bag.Clock += Mathf.Min(delta, 1f); } if (Time.unscaledTime >= nextGains) { nextGains = Time.unscaledTime + 1.5f; if (gains.Count > 0) { if (Plugin.ShowGains.Value) { Feed.Post(Feed.List(gains, "+")); } gains.Clear(); } if (spilled.Count > 0) { string text = Feed.List(spilled); Feed.Post("Bag full: " + text + " fell on the ground"); Plugin.Diag("bag full", ("onGround", text)); spilled.Clear(); } } CheckSpots(localPlayer); LeftPins.Sync(left, LeftRevision); if (Time.unscaledTime < nextSweep) { return; } nextSweep = Time.unscaledTime + 1f; if (!Plugin.Expires.Value) { return; } gone.Clear(); bag.Expire(RareItems.NeverExpires, gone); if (gone.Count <= 0) { return; } lines.Clear(); int num = 0; foreach (Gone item in gone) { lines.Add(new KeyValuePair<string, int>(item.Name, item.Amount)); num += item.Amount; announced.Remove(item.Name); } Feed.Post("Expired: " + Feed.List(lines)); Plugin.Diag("expired", ("kinds", gone.Count), ("pieces", num)); } private static void LoadCarry(Player player) { player.m_customData.TryGetValue("ComputerAutoLootbag.carry.v1", out var value); carryReadable = SealRules.TryParse(value, out List<SealedBag> entries); seals = (carryReadable ? entries : new List<SealedBag>()); if (!carryReadable) { if (!player.m_customData.ContainsKey("ComputerAutoLootbag.carry.v1.unreadable")) { player.m_customData["ComputerAutoLootbag.carry.v1.unreadable"] = value ?? ""; } Plugin.Log.LogError((object)"Computer Auto Lootbag: sealed bag data is unreadable; retained unchanged. Carrier transfers are disabled for this character."); } } private static void SaveCarry(Player player) { if (carryReadable) { player.m_customData["ComputerAutoLootbag.carry.v1"] = SealRules.Serialize(seals); } } private static void CommitCarry(BagModel active, List<LeftBag> remaining, List<SealedBag> entries) { Player localPlayer = Player.m_localPlayer; string value = active.Serialize(); string value2 = LeftBags.Serialize(remaining); string value3 = SealRules.Serialize(entries); Dictionary<string, string> dictionary = new Dictionary<string, string>(localPlayer.m_customData); try { localPlayer.m_customData["ComputerAutoLootbag.v1"] = value; localPlayer.m_customData["ComputerAutoLootbag.left.v1"] = value2; localPlayer.m_customData["ComputerAutoLootbag.carry.v1"] = value3; } catch { string[] array = new string[3] { "ComputerAutoLootbag.v1", "ComputerAutoLootbag.left.v1", "ComputerAutoLootbag.carry.v1" }; foreach (string key in array) { if (dictionary.TryGetValue(key, out var value4)) { localPlayer.m_customData[key] = value4; } else { localPlayer.m_customData.Remove(key); } } throw; } bag = active; left = remaining; seals = entries; LeftRevision++; } internal static bool SealCorpse(long world, ZDOID tomb, long carrier, string carrierName, out string receipt, out string note) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) receipt = ""; note = "No Computer Lootbag remains at this corpse."; if (!Ready || !carryReadable) { note = "Owner's sealed bag storage is unavailable."; return false; } SealedBag sealedBag = seals.FirstOrDefault((SealedBag e) => e.Escrow && SealRules.SameCorpse(e.Record, world, ((ZDOID)(ref tomb)).UserID, ((ZDOID)(ref tomb)).ID)); if (sealedBag != null) { if (sealedBag.Carrier != carrier) { note = "This loot bag is already carried by " + sealedBag.CarrierName + "."; return false; } receipt = Receipt(sealedBag); note = "Sealed bag already assigned to you."; return true; } int num = left.FindIndex((LeftBag r) => SealRules.SameCorpse(r, world, ((ZDOID)(ref tomb)).UserID, ((ZDOID)(ref tomb)).ID)); if (num < 0) { return false; } LeftBag leftBag = left[num]; List<LeftBag> list = new List<LeftBag>(left); list.RemoveAt(num); if (carrier == owner) { if (!SealRules.TryRestore(bag, leftBag.Bag, Mathf.Clamp(Plugin.MaxPerItem.Value, 1, 100000), out BagModel restored)) { note = "Loot bag full. Make room; all corpse loot stays sealed."; Plugin.Diag("corpse button", ("owner", owner), ("carrier", carrier), ("pieces", leftBag.Bag.Pieces), ("result", "bag full, stays sealed")); return false; } CommitCarry(restored, list, new List<SealedBag>(seals)); note = "Your Computer Lootbag was recovered."; } else { SealedBag sealedBag2 = new SealedBag { Token = Guid.NewGuid().ToString("N"), Owner = owner, OwnerName = Player.m_localPlayer.GetPlayerName(), Carrier = carrier, CarrierName = carrierName, Escrow = true, Record = leftBag }; List<SealedBag> entries = new List<SealedBag>(seals) { sealedBag2 }; CommitCarry(bag, list, entries); receipt = Receipt(sealedBag2); note = "Carrying " + sealedBag2.OwnerName + "'s sealed Computer Lootbag."; Feed.Post(carrierName + " is carrying your sealed Computer Lootbag."); } Plugin.Diag("corpse button", ("owner", owner), ("carrier", carrier), ("pieces", leftBag.Bag.Pieces), ("result", (carrier == owner) ? "restored to own bag" : "sealed, carried by friend")); return true; } private static string Receipt(SealedBag source) { return SealRules.Serialize(new SealedBag[1] { new SealedBag { Token = source.Token, Owner = source.Owner, OwnerName = source.OwnerName, Carrier = source.Carrier, CarrierName = source.CarrierName, Record = source.Record, Escrow = false } }); } internal static bool AcceptReceipt(string receipt, long expectedOwner) { if (!Ready || !carryReadable || !SealRules.TryParse(receipt, out List<SealedBag> entries) || entries.Count != 1) { return false; } SealedBag e = entries[0]; if (e.Escrow || e.Owner != expectedOwner || e.Carrier != owner) { return false; } if (seals.Any((SealedBag s) => s.Token == e.Token)) { return true; } List<SealedBag> entries2 = new List<SealedBag>(seals) { e }; CommitCarry(bag, new List<LeftBag>(left), entries2); return true; } internal static int ReturnSeal(string token, long carrier, out string note) { note = "This sealed bag is no longer assigned to you (already returned or recalled)."; if (!Ready || !carryReadable || ((Character)Player.m_localPlayer).IsDead()) { note = "Owner must be alive and have readable bag storage."; return 0; } SealedBag sealedBag = seals.FirstOrDefault((SealedBag e) => e.Escrow && e.Token == token && e.Owner == owner && e.Carrier == carrier); if (sealedBag == null) { return 2; } if (!SealRules.TryRestore(bag, sealedBag.Record.Bag, Mathf.Clamp(Plugin.MaxPerItem.Value, 1, 100000), out BagModel restored)) { note = ((sealedBag.Carrier == owner) ? "Your active bag is full. Make room; this recovered bag stays sealed with paused timers." : "Owner's loot bag is full. Sealed contents remain with the carrier."); return 0; } List<SealedBag> list = new List<SealedBag>(seals); list.Remove(sealedBag); CommitCarry(restored, new List<LeftBag>(left), list); note = "Sealed Computer Lootbag returned to " + sealedBag.OwnerName + "."; Feed.Post("Your sealed Computer Lootbag was returned."); Plugin.Diag("sealed returned", ("token", token), ("carrier", carrier), ("pieces", sealedBag.Record.Bag.Pieces)); return 1; } internal static void ForgetReceipt(string token) { if (Ready && carryReadable) { List<SealedBag> entries = seals.Where((SealedBag e) => e.Escrow || e.Token != token).ToList(); CommitCarry(bag, new List<LeftBag>(left), entries); } } internal static void RecallSeal(SealedBag entry) { if (entry.Escrow && Ready && entry.Owner == owner) { string note; int num = ReturnSeal(entry.Token, entry.Carrier, out note); Plugin.Diag("recall", ("carrier", entry.Carrier), ("pieces", entry.Record.Bag.Pieces), ("result", num switch { 2 => "already returned", 1 => "ok", _ => "refused: " + note, })); Feed.Post(note); } } internal static void RecoverOwnCorpse(Container? container) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; TombStone val = default(TombStone); ZNetView val2 = default(ZNetView); if (!Ready || !carryReadable || !Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !Object.op_Implicit((Object)(object)container) || !((Component)container).TryGetComponent<TombStone>(ref val) || !((Component)container).TryGetComponent<ZNetView>(ref val2) || !val2.IsValid() || !val2.IsOwner() || !CarryNet.CanAccessCorpse(container, localPlayer)) { return; } ZDO zDO = val2.GetZDO(); long num = zDO.GetLong(ZDOVars.s_owner, 0L); ZDOID id = zDO.m_uid; if (!SealRules.TryRecoverOwn(bag, left, owner, num, ZNet.instance.GetWorldUID(), ((ZDOID)(ref id)).UserID, ((ZDOID)(ref id)).ID, Mathf.Clamp(Plugin.MaxPerItem.Value, 1, 100000), out BagModel restored, out List<LeftBag> remaining)) { if (num == owner) { int num2 = left.FindIndex((LeftBag r) => SealRules.SameCorpse(r, ZNet.instance.GetWorldUID(), ((ZDOID)(ref id)).UserID, ((ZDOID)(ref id)).ID)); if (num2 >= 0) { Recover(num2, "own native corpse (sealed)"); } } } else { int num3 = restored.Pieces - bag.Pieces; CommitCarry(restored, remaining, new List<SealedBag>(seals)); Feed.Post("Your Computer Lootbag was recovered."); Plugin.Diag("recovered", ("pieces", num3), ("by", "own native corpse"), ("bagsLeft", left.Count)); } } } internal static class AzothLink { internal const string ApiType = "Computer.Alchemy.AzothApi"; internal const string Reason = "Lootbag:TurnToAzoth"; internal const int Contract = 4; private static bool searched; private static Func<bool>? available; private static Func<string, int, int>? amountFor; private static Func<string, int, int>? valueOf; private static Action<Player, string, int, int, string, Func<bool>, Action<bool, int, float, string>>? convert; private static string quotedName = ""; private static int quotedHeld = -1; private static int quotedAmount; private static int quotedAzoth; private static float quotedUntil; internal static string Status { get; private set; } = "Computer Alchemy is not loaded; Azoth conversion is unavailable."; internal static bool Available { get { Find(); if (available == null) { return false; } try { bool num = available(); Status = (num ? "" : "Azoth conversion is off on this server or Alchemy isn't ready yet."); return num; } catch (Exception error) { Status = "Alchemy availability check failed. Your loot is unchanged; try again."; Faults.Report("AzothLink.available", error); return false; } } } internal static bool CheckedAvailable { get { if (Available) { return convert != null; } return false; } } private static void Find() { if (searched) { return; } searched = true; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if ((type = assemblies[i].GetType("Computer.Alchemy.AzothApi", throwOnError: false)) != null) { break; } } if (type == null) { return; } if (!(type.GetField("ContractVersion", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) is int num) || num < 4) { Status = "Update Computer Alchemy to 0.0.55 or newer for safe lootbag conversion."; return; } MethodInfo methodInfo = type.GetProperty("ConvertAvailable", BindingFlags.Static | BindingFlags.Public)?.GetGetMethod(); MethodInfo method = type.GetMethod("ConvertAmount", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(int) }, null); MethodInfo method2 = type.GetMethod("AzothValue", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(int) }, null); MethodInfo method3 = type.GetMethod("BeginConvertChecked", BindingFlags.Static | BindingFlags.Public, null, new Type[7] { typeof(Player), typeof(string), typeof(int), typeof(int), typeof(string), typeof(Func<bool>), typeof(Action<bool, int, float, string>) }, null); if (methodInfo?.ReturnType != typeof(bool) || method?.ReturnType != typeof(int) || method2?.ReturnType != typeof(int) || method3?.ReturnType != typeof(void)) { Status = "Computer Alchemy checked conversion API is incompatible; your loot is unchanged."; return; } amountFor = (Func<string, int, int>)Delegate.CreateDelegate(typeof(Func<string, int, int>), method); valueOf = (Func<string, int, int>)Delegate.CreateDelegate(typeof(Func<string, int, int>), method2); convert = (Action<Player, string, int, int, string, Func<bool>, Action<bool, int, float, string>>)Delegate.CreateDelegate(typeof(Action<Player, string, int, int, string, Func<bool>, Action<bool, int, float, string>>), method3); available = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), methodInfo); Plugin.Diag("azothLink", ("contract", num), ("result", "checked v4 bound")); } catch (Exception error) { Status = "Could not bind Computer Alchemy. Your loot is unchanged."; Faults.Report("AzothLink.find", error); } } internal static void Forget() { quotedHeld = -1; } internal static void Quote(string name, int held, out int amount, out int azoth) { amount = (azoth = 0); if (!Available || amountFor == null || valueOf == null || held <= 0) { return; } if (name == quotedName && held == quotedHeld && Time.unscaledTime < quotedUntil) { amount = quotedAmount; azoth = quotedAzoth; return; } try { amount = Math.Max(0, Math.Min(held, amountFor(name, held))); azoth = ((amount > 0) ? Math.Max(0, valueOf(name, amount)) : 0); if (azoth <= 0) { amount = 0; } Status = ((amount > 0) ? "" : "Alchemy won't accept this item or quantity under its current rates and whole-batch limits."); } catch (Exception error) { amount = (azoth = 0); Status = "Alchemy could not quote this item. Your loot is unchanged; try again."; Faults.Report("AzothLink.quote", error); } quotedName = name; quotedHeld = held; quotedAmount = amount; quotedAzoth = azoth; quotedUntil = Time.unscaledTime + 0.5f; } internal static bool ConvertChecked(Player player, string name, int amount, int expectedAzoth, Func<bool> consume, Action<bool, int, float, string> done) { Forget(); if (!CheckedAvailable) { done(arg1: false, 0, 0f, Status); return true; } convert(player, name, amount, expectedAzoth, "Lootbag:TurnToAzoth", consume, done); return true; } } internal sealed class AzothPlan { internal sealed class Row { internal readonly int Held; internal int Pieces; internal long Azoth; internal readonly List<AzothQuote> Batches = new List<AzothQuote>(); internal readonly List<int> HeldBefore = new List<int>(); internal Row(int held) { Held = held; } } internal readonly BagModel Source; internal readonly int Revision; internal readonly Dictionary<string, Row> Rows = new Dictionary<string, Row>(StringComparer.Ordinal); private readonly Queue<string> pending; private readonly Func<string, int, AzothQuote> quote; private string item = ""; private int remaining; internal bool Done { get; private set; } internal bool Valid { get; private set; } = true; internal long Total { get; private set; } internal AzothPlan(BagModel source, Func<string, int, AzothQuote> quote) { Source = source; Revision = source.Revision; this.quote = quote; foreach (KeyValuePair<string, BagItem> item in source.Items) { Rows.Add(item.Key, new Row(item.Value.Total)); } pending = new Queue<string>(Rows.Keys.OrderBy<string, string>((string n) => n, StringComparer.Ordinal)); } internal bool Current(BagModel? source) { if (Valid && source != null && Source == source) { return source.Revision == Revision; } return false; } internal void Step() { if (Done) { return; } if (!Current(Source)) { Valid = false; Done = true; return; } if (remaining <= 0) { if (pending.Count == 0) { Done = true; return; } item = pending.Dequeue(); remaining = Rows[item].Held; } try { AzothQuote azothQuote = quote(item, remaining); if (azothQuote.Amount <= 0 || azothQuote.Azoth <= 0) { remaining = 0; return; } if (azothQuote.Amount > remaining) { Valid = false; Done = true; return; } Row row = Rows[item]; row.HeldBefore.Add(remaining); row.Batches.Add(azothQuote); row.Pieces += azothQuote.Amount; row.Azoth += azothQuote.Azoth; Total += azothQuote.Azoth; remaining -= azothQuote.Amount; } catch { Valid = false; Done = true; } } internal bool Matches(string name, int held, int batch, AzothQuote offered) { if (!Done || !Valid || !Rows.TryGetValue(name, out Row value) || batch < 0 || batch >= value.Batches.Count) { return false; } AzothQuote azothQuote = value.Batches[batch]; if (value.HeldBefore[batch] == held && azothQuote.Amount == offered.Amount) { return azothQuote.Azoth == offered.Azoth; } return false; } } internal static class BagButtonsUi { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__22_0; public static UnityAction <>9__22_1; internal void <Build>b__22_0() { bagClicked = true; } internal void <Build>b__22_1() { switchClicked = true; } } private static RectTransform? root; private static Image? bagEdge; private static Image? bagFill; private static Image? useEdge; private static Image? useFill; private static Image? track; private static Image? knob; private static RawImage? emblem; private static TMP_Text? label; private static TMP_Text? badgeText; private static Sprite? round; private static bool bagClicked; private static bool switchClicked; private static bool splitWasOpen; private static float nextSplitLog; internal static bool SplitOpen { get { InventoryGui instance = InventoryGui.instance; if (instance != null && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_splitDialog)) { return instance.m_splitDialog.IsActive; } return false; } } internal static void Hide() { bagClicked = (switchClicked = (splitWasOpen = false)); if (Object.op_Implicit((Object)(object)root) && ((Component)root).gameObject.activeSelf) { ((Component)root).gameObject.SetActive(false); } } internal static bool TakeBagClick() { bool result = bagClicked; bagClicked = false; return result; } internal static bool TakeSwitchClick() { bool result = switchClicked; switchClicked = false; return result; } internal static void Place(Rect bag, Rect use, float unit, bool highlight, bool on, string badge, bool urgent) { //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_05ab: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_05b0: Unknown result type (might be due to invalid IL or missing references) //IL_05d2: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Unknown result type (might be due to invalid IL or missing references) //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0692: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; RectTransform val = (RectTransform)(Object.op_Implicit((Object)(object)instance) ? (/*isinst with value type is only supported in some contexts*/ ?? /*isinst with value type is only supported in some contexts*/) : null); if (!Object.op_Implicit((Object)(object)val)) { Hide(); return; } if (!Object.op_Implicit((Object)(object)root)) { Build(val); } else if ((Object)(object)((Transform)root).parent != (Object)(object)val) { ((Transform)root).SetParent((Transform)(object)val, false); } SplitDialog splitDialog = instance.m_splitDialog; Transform val2 = (Object.op_Implicit((Object)(object)splitDialog) ? ((Component)splitDialog).transform : null); while (Object.op_Implicit((Object)(object)val2) && (Object)(object)val2.parent != (Object)(object)val) { val2 = val2.parent; } bool flag = Object.op_Implicit((Object)(object)val2); if (flag && ((Transform)root).GetSiblingIndex() > val2.GetSiblingIndex()) { ((Transform)root).SetSiblingIndex(val2.GetSiblingIndex()); } bool splitOpen = SplitOpen; if (splitOpen && !splitWasOpen && Time.unscaledTime >= nextSplitLog) { nextSplitLog = Time.unscaledTime + 1f; Plugin.Diag("inventory footer", ("key", "split"), ("result", flag ? "behind dialog" : "hidden for dialog")); } splitWasOpen = splitOpen; if (splitOpen && !flag) { ((Component)root).gameObject.SetActive(false); return; } Image? obj = bagEdge; bool raycastTarget = (((Graphic)useEdge).raycastTarget = !splitOpen); ((Graphic)obj).raycastTarget = raycastTarget; Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>(); Camera val3 = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); Rect area = Rect.MinMaxRect(((Rect)(ref bag)).x, ((Rect)(ref bag)).y, ((Rect)(ref use)).xMax, Mathf.Max(((Rect)(ref bag)).yMax, ((Rect)(ref use)).yMax)); Vector2 val4 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val, new Vector2(((Rect)(ref area)).x, (float)Screen.height - ((Rect)(ref area)).y), val3, ref val4); Vector2 val5 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(val, new Vector2(((Rect)(ref area)).xMax, (float)Screen.height - ((Rect)(ref area)).yMax), val3, ref val5); RectTransform? obj2 = root; Vector2 anchorMin = (root.anchorMax = val.pivot); obj2.anchorMin = anchorMin; root.pivot = new Vector2(0f, 1f); root.anchoredPosition = val4; root.sizeDelta = new Vector2(val5.x - val4.x, val4.y - val5.y); float k = ((((Rect)(ref area)).height > 0f) ? (root.sizeDelta.y / ((Rect)(ref area)).height) : 1f); float refPpu = (Object.op_Implicit((Object)(object)componentInParent) ? componentInParent.rootCanvas.referencePixelsPerUnit : 100f); Vector2 val6 = Vector2.op_Implicit(ZInput.pointerPosition); bool flag3 = RectTransformUtility.RectangleContainsScreenPoint(((Graphic)bagEdge).rectTransform, val6, val3); bool flag4 = RectTransformUtility.RectangleContainsScreenPoint(((Graphic)useEdge).rectTransform, val6, val3); Body(bagEdge, bagFill, bag, flag3 || highlight); Body(useEdge, useFill, use, flag4); float num = ((Rect)(ref bag)).height / unit; float num2 = num - 6f; Texture2D val7 = BagGui.Emblem; emblem.texture = (Texture)(object)val7; ((Behaviour)emblem).enabled = Object.op_Implicit((Object)(object)val7); Put((Graphic)(object)emblem, new Rect(((Rect)(ref bag)).x + 8f * unit, ((Rect)(ref bag)).y + 3f * unit, num2 * unit, num2 * unit)); label.fontSize = (float)BagGui.QolLine.Font * unit * k; ((Graphic)label).color = BagGui.Text; Put((Graphic)(object)label, new Rect(((Rect)(ref bag)).x + (Object.op_Implicit((Object)(object)val7) ? (num2 + 14f) : 12f) * unit, ((Rect)(ref bag)).y, 100f * unit, ((Rect)(ref bag)).height)); badgeText.text = badge; badgeText.fontSize = 14f * unit * k; ((Graphic)badgeText).color = (urgent ? BagGui.Warn : BagGui.Muted); Put((Graphic)(object)badgeText, new Rect(((Rect)(ref bag)).xMax - 82f * unit, ((Rect)(ref bag)).y, 72f * unit, ((Rect)(ref bag)).height)); float num3 = Mathf.Min(22f, num - 10f); float num4 = num3 * 54f / 28f; float num5 = num3 - 6f; Rect screen = default(Rect); ((Rect)(ref screen))..ctor(((Rect)(ref use)).center.x - num4 * unit / 2f, ((Rect)(ref use)).center.y - num3 * unit / 2f, num4 * unit, num3 * unit); Color tint = (Color)(flag4 ? new Color(1f, 0.93f, 0.78f, 1f) : Color.white); Skin(track, on ? "switch_track_on" : "switch_track_off", on ? BagGui.Gold : BagGui.ButtonFlat, tint); Skin(knob, on ? "switch_knob_on" : "switch_knob_off", on ? BagGui.Text : BagGui.Muted, tint); Image? obj3 = track; float pixelsPerUnitMultiplier = (knob.pixelsPerUnitMultiplier = 1f); obj3.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier; Put((Graphic)(object)track, screen); Put((Graphic)(object)knob, new Rect(on ? (((Rect)(ref screen)).xMax - (num5 + 3f) * unit) : (((Rect)(ref screen)).x + 3f * unit), ((Rect)(ref screen)).y + 3f * unit, num5 * unit, num5 * unit)); if ((Object)(object)track.sprite == (Object)(object)round) { track.pixelsPerUnitMultiplier = 32f * refPpu / 100f / Mathf.Max(0.01f, num3 / 2f * unit * k); } if ((Object)(object)knob.sprite == (Object)(object)round) { knob.pixelsPerUnitMultiplier = 32f * refPpu / 100f / Mathf.Max(0.01f, num5 / 2f * unit * k); } if (!((Component)root).gameObject.activeSelf) { ((Component)root).gameObject.SetActive(true); } void Body(Image edge, Image fill, Rect screen2, bool hover) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) float num7 = 32f * refPpu / 100f / Mathf.Max(0.01f, 9f * unit * k); float pixelsPerUnitMultiplier2 = (fill.pixelsPerUnitMultiplier = num7); edge.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier2; Put((Graphic)(object)edge, screen2); Put((Graphic)(object)fill, new Rect(((Rect)(ref screen2)).x + 1f, ((Rect)(ref screen2)).y + 1f, ((Rect)(ref screen2)).width - 2f, ((Rect)(ref screen2)).height - 2f)); ((Graphic)edge).color = BagGui.ControlEdge; ((Graphic)fill).color = (hover ? Color.Lerp(BagGui.ButtonFlat, Color.white, 0.06f) : BagGui.ButtonFlat); } void Put(Graphic g, Rect val8) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = g.rectTransform; rectTransform.anchoredPosition = new Vector2((((Rect)(ref val8)).x - ((Rect)(ref area)).x) * k, (0f - (((Rect)(ref val8)).y - ((Rect)(ref area)).y)) * k); rectTransform.sizeDelta = new Vector2(((Rect)(ref val8)).width * k, ((Rect)(ref val8)).height * k); } } private static void Skin(Image image, string kit, Color flat, Color tint) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Sprite val = BagGui.Kit(kit); image.sprite = (Sprite)(Object.op_Implicit((Object)(object)val) ? ((object)val) : ((object)round)); image.type = (Type)1; ((Graphic)image).color = (Object.op_Implicit((Object)(object)val) ? tint : (flat * tint)); } private static void Build(RectTransform parent) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)round)) { Texture2D val = BagGui.Rounded(); round = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(32f, 32f, 32f, 32f)); ((Object)round).hideFlags = (HideFlags)61; } root = (RectTransform)new GameObject("ComputerAutoLootbag_Buttons", new Type[1] { typeof(RectTransform) }).transform; ((Transform)root).SetParent((Transform)(object)parent, false); TMP_Text componentInChildren = ((Component)parent).GetComponentInChildren<TMP_Text>(true); bagEdge = NewImage("BagEdge", raycast: true); bagFill = NewImage("BagFill", raycast: false); emblem = NewChild("Emblem", typeof(RawImage)).GetComponent<RawImage>(); ((Graphic)emblem).raycastTarget = false; label = NewText("Label", componentInChildren, (TextAlignmentOptions)4097); label.text = "Loot bag"; label.fontStyle = (FontStyles)1; badgeText = NewText("Badge", componentInChildren, (TextAlignmentOptions)4100); useEdge = NewImage("SwitchEdge", raycast: true); useFill = NewImage("SwitchFill", raycast: false); track = NewImage("Track", raycast: false); knob = NewImage("Knob", raycast: false); Image? target = bagEdge; object obj = <>c.<>9__22_0; if (obj == null) { UnityAction val2 = delegate { bagClicked = true; }; <>c.<>9__22_0 = val2; obj = (object)val2; } Clickable(target, (UnityAction)obj); Image? target2 = useEdge; object obj2 = <>c.<>9__22_1; if (obj2 == null) { UnityAction val3 = delegate { switchClicked = true; }; <>c.<>9__22_1 = val3; obj2 = (object)val3; } Clickable(target2, (UnityAction)obj2); } private static GameObject NewChild(string name, Type graphic) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), graphic }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)root, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; return val; } private static Image NewImage(string name, bool raycast) { Image component = NewChild(name, typeof(Image)).GetComponent<Image>(); component.sprite = round; component.type = (Type)1; ((Graphic)component).raycastTarget = raycast; return component; } private static TMP_Text NewText(string name, TMP_Text? vanilla, TextAlignmentOptions align) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0027: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0053: 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_0087: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.SetActive(false); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)root, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; TextMeshProUGUI val5 = val.AddComponent<TextMeshProUGUI>(); if (Object.op_Implicit((Object)(object)vanilla)) { ((TMP_Text)val5).font = vanilla.font; ((TMP_Text)val5).fontSharedMaterial = vanilla.fontSharedMaterial; } ((TMP_Text)val5).alignment = align; ((TMP_Text)val5).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val5).overflowMode = (TextOverflowModes)0; ((Graphic)val5).raycastTarget = false; val.SetActive(true); return (TMP_Text)(object)val5; } private static void Clickable(Image target, UnityAction click) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Button obj = ((Component)target).gameObject.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)target; ((Selectable)obj).transition = (Transition)0; Navigation navigation = ((Selectable)obj).navigation; ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj).navigation = navigation; ((UnityEvent)obj.onClick).AddListener(click); } } internal static class BagGui { internal static class QolLine { private delegate bool NextLine(out float x, out float y, out float scale); private delegate bool UnitsLine(out float height, out float gapY, out int fontSize, out float nextX); private static bool searched; private static NextLine? next; private static Func<bool>? suppressed; internal static float Height = 34f; internal static float GapY = 2f; internal static float Gap = 8f; internal static int Font = 16; private static bool unitsSearched; private static UnitsLine? units; internal static bool ButtonsSuppressed { get { Find(); if (suppressed == null) { return false; } try { return suppressed(); } catch (Exception error) { Faults.Report("QolLine.suppressed", error); return true; } } } internal static bool Found { get { Find(); return next != null; } } private static void Find() { if (searched) { return; } searched = true; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("Computer.QOL.InventoryLineApi", throwOnError: false); if (type != null) { break; } } if (type == null) { return; } MethodInfo method = type.GetMethod("TryGetNext", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(float).MakeByRefType(), typeof(float).MakeByRefType(), typeof(float).MakeByRefType() }, null); if (method == null || method.ReturnType != typeof(bool)) { return; } float num = Constant(type, "Height"); float num2 = Constant(type, "FontSize"); float num3 = Constant(type, "GapY"); float num4 = Constant(type, "Gap"); if (num >= 20f && num <= 80f) { Height = num; } if (num2 >= 10f && num2 <= 40f) { Font = Mathf.RoundToInt(num2); } if (num3 >= 0f && num3 <= 20f) { GapY = num3; } if (num4 >= 0f && num4 <= 30f) { Gap = num4; } PropertyInfo property = type.GetProperty("ButtonsSuppressed", BindingFlags.Static | BindingFlags.Public); if (property?.PropertyType == typeof(bool) && property.GetIndexParameters().Length == 0) { MethodInfo getMethod = property.GetGetMethod(); if ((object)getMethod != null && getMethod.IsStatic) { suppressed = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), getMethod); } } next = (NextLine)Delegate.CreateDelegate(typeof(NextLine), method); } catch (Exception error) { Faults.Report("QolLine.find", error); } } private static float Constant(Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public); if (field != null && field.IsLiteral) { object rawConstantValue = field.GetRawConstantValue(); if (rawConstantValue is float) { return (float)rawConstantValue; } } return -1f; } internal static bool TryGetNext(out float x, out float y, out float scale) { x = (y = (scale = 0f)); Find(); if (next == null) { return false; } try { if (!next(out x, out y, out scale)) { return false; } return scale > 0f; } catch (Exception error) { Faults.Report("QolLine.read", error); next = null; return false; } } internal static bool TryGetUnits(out float nextX) { nextX = 0f; if (!unitsSearched) { unitsSearched = true; try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("Computer.QOL.QolUiKit", throwOnError: false); if (!(type == null)) { MethodInfo method = type.GetMethod("TryGetInventoryLine", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(float).MakeByRefType(), typeof(float).MakeByRefType(), typeof(int).MakeByRefType(), typeof(float).MakeByRefType() }, null); if (method != null && method.ReturnType == typeof(bool)) { units = (UnitsLine)Delegate.CreateDelegate(typeof(UnitsLine), method); } break; } } } catch (Exception error) { Faults.Report("QolLine.findUnits", error); } } if (units == null) { return false; } try { if (!units(out var height, out var gapY, out var fontSize, out var nextX2)) { return false; } if (nextX2 <= 0f || nextX2 > 600f) { return false; } if (height >= 20f && height <= 80f) { Height = height; } if (gapY >= 0f && gapY <= 20f) { GapY = gapY; } if (fontSize >= 10 && fontSize <= 40) { Font = fontSize; } Gap = 6f; nextX = nextX2; return true; } catch (Exception error2) { Faults.Report("QolLine.readUnits", error2); units = null; return false; } } } internal static Color Gold = Hex("e6bd66"); internal static Color Text = Hex("f1ebdf"); internal static Color Muted = Hex("aaa293"); internal static Color Soft = Hex("aaa293"); internal static Color Dim = Hex("736c60"); internal static Color Warn = Hex("f2a44b"); internal static Color Danger = Hex("f07a6c"); internal static Color Good = Hex("83c77e"); internal static Color Panel = Hex("11151b", 0.98f); internal static readonly Color RowFlat = new Color(1f, 1f, 1f, 0.05f); internal static readonly Color RowOver = Hex("e6bd66", 0.1f); internal static readonly Color Well = Hex("0c0f14"); internal static readonly Color ButtonFlat = Hex("1c222b"); internal static readonly Color Line = Hex("e6bd66", 0.45f); internal static readonly Color Edge = Hex("4a3c26"); internal static readonly Color Shadow = new Color(0f, 0f, 0f, 0.85f); internal static readonly Color ControlEdge = Hex("6d5632"); internal static readonly Color PrimaryFill = Hex("2a2118"); internal static readonly Color PrimaryEdge = Hex("91703d"); internal static readonly Color DangerFill = Hex("421f1c"); internal static readonly Color DangerEdge = Hex("7a3a33"); internal static readonly Color RowEdge = Hex("272d36"); internal static readonly Color WellEdge = Hex("323a45"); internal static readonly Color YellowFill = Hex("e2b862"); internal static readonly Color YellowEdge = Hex("3a2c16"); internal static readonly Color YellowText = Hex("2a2118"); internal const float WindowRadius = 20f; internal const float PanelRadius = 12f; internal const float ControlRadius = 9f; private static bool paletteRead; private static Func<float, float, float, float, float>? qolWindowScale; private static MethodInfo? kitSprite; private static bool kitSearched; private static readonly Dictionary<string, Sprite?> sprites = new Dictionary<string, Sprite>(StringComparer.Ordinal); private static readonly Dictionary<int, GUIStyle> styles = new Dictionary<int, GUIStyle>(); private static Font? body; private static Font? bold; private static float nextFontSearch; private static Texture2D? rounded; private static readonly Dictionary<string, int> fitNames = new Dictionary<string, int>(StringComparer.Ordinal); private static readonly Dictionary<string, int> fitNotes = new Dictionary<string, int>(StringComparer.Ordinal); private static readonly Dictionary<string, int> fitAzoth = new Dictionary<string, int>(StringComparer.Ordinal); private static readonly Dictionary<string, int> fitBulk = new Dictionary<string, int>(StringComparer.Ordinal); private static readonly Dictionary<string, int> fitFoot = new Dictionary<string, int>(StringComparer.Ordinal); private static Font? fitBody; private static Font? fitBold; private static Texture2D? emblem; private static bool emblemLoaded; internal static Texture2D? Emblem { get { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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: Expected O, but got Unknown if (emblemLoaded) { return emblem; } emblemLoaded = true; try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Computer.AutoLootbag.Assets.bag.png"); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = "ComputerAutoLootbag_Bag", wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; if (ImageConversion.LoadImage(val, memoryStream.ToArray(), true)) { emblem = val; } } catch (Exception error) { Faults.Report("BagGui.Emblem", error); } return emblem; } } private static void Palette() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if (paletteRead) { return; } paletteRead = true; try { Type kit = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if ((kit = assembly.GetType("Computer.QOL.QolUiKit", throwOnError: false)) != null) { break; } } if (kit == null) { return; } FieldInfo field = kit.GetField("Version", BindingFlags.Static | BindingFlags.Public); if (((field != null && field.GetValue(null) is int num) ? num : 0) >= 2) { Gold = Read("Gold", Gold); Text = Read("Text", Text); Muted = (Soft = Read("Muted", Muted)); Dim = Read("Dim", Dim); Good = Read("Ok", Good); Warn = Read("Warn", Warn); Danger = Read("DangerText", Danger); Color val = Read("Panel", Panel); Panel = new Color(val.r, val.g, val.b, 0.98f); MethodInfo method = kit.GetMethod("WindowScale", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(float), typeof(float), typeof(float), typeof(float) }, null); if (method != null && method.ReturnType == typeof(float)) { qolWindowScale = (Func<float, float, float, float, float>)Delegate.CreateDelegate(typeof(Func<float, float, float, float, float>), method); } styles.Clear(); } Color Read(string name, Color fallback) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) object obj = kit.GetProperty(name, BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj is Color) { return (Color)obj; } return fallback; } } catch (Exception error) { Faults.Report("BagGui.palette", error); } } internal static float WindowScale(float screenWidth, float screenHeight, float width, float height) { Palette(); if (qolWindowScale != null) { try { return qolWindowScale(screenWidth, screenHeight, width, height); } catch (Exception error) { Faults.Report("BagGui.windowScale", error); qolWindowScale = null; } } return WindowRules.WindowScale(screenWidth, screenHeight, width, height); } private static Color Hex(string hex, float alpha = 1f) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) return new Color((float)Convert.ToInt32(hex.Substring(0, 2), 16) / 255f, (float)Convert.ToInt32(hex.Substring(2, 2), 16) / 255f, (float)Convert.ToInt32(hex.Substring(4, 2), 16) / 255f, alpha); } internal static Sprite? Kit(string name) { if (sprites.TryGetValue(name, out Sprite value)) { return value; } if (!kitSearched) { kitSearched = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("Computer.QOL.QolUiKit", throwOnError: false); if (!(type == null)) { kitSprite = type.GetMethod("TryGetSprite", BindingFlags.Static | BindingFlags.Public); break; } } } Sprite val = null; if (kitSprite != null) { try { object[] array = new object[2] { name, null }; object obj = kitSprite.Invoke(null, array); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { object obj2 = array[1]; val = (Sprite)((obj2 is Sprite) ? obj2 : null); } } catch (Exception error) { Faults.Report("BagGui.Kit", error); kitSprite = null; } } return sprites[name] = val; } private static void Fonts() { if (Object.op_Implicit((Object)(object)body) || Time.realtimeSinceStartup < nextFontSearch) { return; } nextFontSearch = Time.realtimeSinceStartup + 10f; Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val in array) { if (((Object)val).name == "AveriaSerifLibre-Regular") { body = val; } else if (((Object)val).name == "AveriaSerifLibre-Bold") { bold = val; } } if (Object.op_Implicit((Object)(object)body)) { styles.Clear(); } } internal static GUIStyle Style(int size, bool strong = false, TextAnchor anchor = (TextAnchor)3, bool wrap = false) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected I4, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00c3: Expected O, but got Unknown Palette(); Fonts(); int key = size * 64 + anchor * 4 + (strong ? 2 : 0) + wrap; if (styles.TryGetValue(key, out GUIStyle value)) { return value; } value = new GUIStyle(GUI.skin.label) { font = ((!strong) ? body : (Object.op_Implicit((Object)(object)bold) ? bold : body)), fontSize = size, fontStyle = (FontStyle)((strong && !Object.op_Implicit((Object)(object)bold)) ? 1 : 0), alignment = anchor, wordWrap = wrap, richText = false, clipping = (TextClipping)0, padding = new RectOffset(0, 0, 0, 0), margin = new RectOffset(0, 0, 0, 0) }; return styles[key] = value; } internal static GUIStyle Title(int size) { return Style(size, strong: true, (TextAnchor)3); } internal static Texture2D Rounded() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)rounded)) { return rounded; } Color32[] array = (Color32[])(object)new Color32[9216]; for (int i = 0; i < 96; i++) { for (int j = 0; j < 96; j++) { float num = (float)j + 0.5f; float num2 = (float)i + 0.5f; float num3 = num - Mathf.Clamp(num, 32f, 64f); float num4 = num2 - Mathf.Clamp(num2, 32f, 64f); array[i * 96 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(255f * Mathf.Clamp01(32.5f - Mathf.Sqrt(num3 * num3 + num4 * num4)))); } } rounded = new Texture2D(96, 96, (TextureFormat)4, false) { hideFlags = (HideFl