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 RustyHeathensServerQoL v1.0.0
RustyHeathensServerQoL.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using RustyHeathens.Automation; using RustyHeathens.Backpacks; using UnityEngine; [assembly: AssemblyProduct("Rusty Heathens Server QoL")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyCompany("RustyLaserGaming")] [assembly: AssemblyDescription("Server-side quality-of-life modules for Heathens' Haven")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("Rusty Heathens Server QoL")] [assembly: AssemblyVersion("1.0.0.0")] namespace RustyHeathens.ServerQoL { internal static class AutoDoorsModule { private sealed class TrackedDoor { internal ZDO Zdo; internal float CloseAt; } private static readonly HashSet<int> DoorPrefabHashes = new HashSet<int>(); private static readonly Dictionary<ZDOID, TrackedDoor> Tracked = new Dictionary<ZDOID, TrackedDoor>(); private static readonly List<ZDOID> ScratchKeys = new List<ZDOID>(); private static bool prefabRegistryReady; private static float nextTick; internal static void Clear() { DoorPrefabHashes.Clear(); Tracked.Clear(); ScratchKeys.Clear(); prefabRegistryReady = false; nextTick = 0f; } internal static void Tick() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null) { return; } if (!Plugin.IsServer() || !instance.DoorsEnabled) { if (Tracked.Count > 0) { Tracked.Clear(); } return; } EnsurePrefabRegistry(); if (!prefabRegistryReady) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextTick) { return; } nextTick = realtimeSinceStartup + 0.2f; ScratchKeys.Clear(); foreach (KeyValuePair<ZDOID, TrackedDoor> item in Tracked) { ScratchKeys.Add(item.Key); } for (int i = 0; i < ScratchKeys.Count; i++) { ZDOID key = ScratchKeys[i]; if (!Tracked.TryGetValue(key, out var value)) { continue; } ZDO zdo = value.Zdo; if (zdo == null || !zdo.IsValid()) { Tracked.Remove(key); continue; } if (!DoorPrefabHashes.Contains(zdo.GetPrefab())) { Tracked.Remove(key); continue; } int num = zdo.GetInt(ZDOVars.s_state, 0); if (num == 0) { Tracked.Remove(key); } else { if (realtimeSinceStartup < value.CloseAt) { continue; } try { zdo.Set(ZDOVars.s_state, 0, true); if (ZDOMan.instance != null) { ZDOMan.instance.ForceSendZDO(zdo.m_uid); } instance.LogDoorEvent("CLOSED", zdo, num); Tracked.Remove(key); } catch (Exception ex) { instance.LogDoorError("Close failed for " + SafeZdoId(zdo) + ": " + ex.Message); value.CloseAt = realtimeSinceStartup + 2f; } } } } internal static void ObserveZdo(ZDO zdo) { //IL_0073: 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_00ae: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null || zdo == null || !Plugin.IsServer() || !instance.DoorsEnabled) { return; } EnsurePrefabRegistry(); if (prefabRegistryReady && zdo.IsValid() && DoorPrefabHashes.Contains(zdo.GetPrefab())) { int num = zdo.GetInt(ZDOVars.s_state, 0); if (num == 0) { Tracked.Remove(zdo.m_uid); return; } if (Tracked.TryGetValue(zdo.m_uid, out var value)) { value.Zdo = zdo; return; } TrackedDoor trackedDoor = new TrackedDoor(); trackedDoor.Zdo = zdo; trackedDoor.CloseAt = Time.realtimeSinceStartup + instance.DoorDelay; Tracked[zdo.m_uid] = trackedDoor; instance.LogDoorEvent("OPEN", zdo, num); } } internal static void ObserveDoor(Door door) { if ((Object)(object)door == (Object)null) { return; } try { ZNetView component = ((Component)door).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ObserveZdo(component.GetZDO()); } } catch { } } private static void EnsurePrefabRegistry() { if (prefabRegistryReady || (Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null) { return; } DoorPrefabHashes.Clear(); List<GameObject> prefabs = ZNetScene.instance.m_prefabs; for (int i = 0; i < prefabs.Count; i++) { GameObject val = prefabs[i]; if (!((Object)(object)val == (Object)null)) { Door val2 = null; try { val2 = val.GetComponentInChildren<Door>(); } catch { } if (!((Object)(object)val2 == (Object)null) && !val2.m_canNotBeClosed && !((Object)(object)val2.m_keyItem != (Object)null)) { DoorPrefabHashes.Add(StringExtensionMethods.GetStableHashCode(((Object)val).name)); } } } if (DoorPrefabHashes.Count > 0) { prefabRegistryReady = true; Plugin instance = Plugin.Instance; if ((Object)(object)instance != (Object)null) { instance.LogDoorRegistry(DoorPrefabHashes.Count); } } } private static string SafeZdoId(ZDO zdo) { try { return (zdo == null) ? "unknown" : ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString(); } catch { return "unknown"; } } } [HarmonyPatch(typeof(ZDO), "Deserialize")] internal static class AutoDoorsZdoDeserializePatch { private static void Postfix(ZDO __instance) { AutoDoorsModule.ObserveZdo(__instance); } } [HarmonyPatch(typeof(Door), "RPC_UseDoor")] internal static class AutoDoorsRpcPatch { private static void Postfix(Door __instance) { AutoDoorsModule.ObserveDoor(__instance); } } [HarmonyPatch(typeof(Door), "UpdateState")] internal static class AutoDoorsUpdateStatePatch { private static void Postfix(Door __instance) { AutoDoorsModule.ObserveDoor(__instance); } } internal static class AutoProcessModule { private sealed class Handoff { internal int Token; internal long Owner; internal long Deadline; internal ZDOID Station; } private static readonly Dictionary<ZDOID, Handoff> Handoffs = new Dictionary<ZDOID, Handoff>(); private static int nextHandoffToken; private static readonly Dictionary<int, Container> BuildableContainerPrefabs = new Dictionary<int, Container>(); private static readonly Dictionary<int, Smelter> ProcessorPrefabs = new Dictionary<int, Smelter>(); private static readonly List<ZDO> DiscoveryObjects = new List<ZDO>(); private static readonly List<ZDO> SectorObjects = new List<ZDO>(); private static readonly List<ZDO> Nearby = new List<ZDO>(); private static readonly HashSet<ZDOID> SeenStations = new HashSet<ZDOID>(); private static readonly HashSet<long> DiscoverySectorKeys = new HashSet<long>(); private static readonly HashSet<int> LoggedProcessorPrefabs = new HashSet<int>(); private static readonly Dictionary<ZDOID, float> LastWaitLog = new Dictionary<ZDOID, float>(); private static bool prefabMapsReady; private static bool registryLogged; private static float nextTick; private static float nextDiscoveryLog; internal static void Clear() { Handoffs.Clear(); nextHandoffToken = 0; BuildableContainerPrefabs.Clear(); ProcessorPrefabs.Clear(); DiscoveryObjects.Clear(); SectorObjects.Clear(); Nearby.Clear(); SeenStations.Clear(); DiscoverySectorKeys.Clear(); LoggedProcessorPrefabs.Clear(); LastWaitLog.Clear(); prefabMapsReady = false; registryLogged = false; nextTick = 0f; nextDiscoveryLog = 0f; } internal static void Tick() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null || !Plugin.IsServer() || !instance.AutoProcessEnabledValue || !EnsurePrefabMaps() || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextTick) { return; } nextTick = realtimeSinceStartup + 2f; List<ZNetPeer> peers = ZNet.instance.GetPeers(); int peerCount = peers?.Count ?? 0; int num = 0; int num2 = 0; SeenStations.Clear(); DiscoverySectorKeys.Clear(); if (peers != null) { for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val == null) { continue; } Vector2s zone = ZoneSystem.GetZone(val.m_refPos); long item = ((long)zone.x << 32) ^ (uint)zone.y; if (!DiscoverySectorKeys.Add(item)) { continue; } DiscoveryObjects.Clear(); ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(1, 0, false), DiscoveryObjects, (List<ZDO>)null); num += DiscoveryObjects.Count; for (int j = 0; j < DiscoveryObjects.Count; j++) { ZDO val2 = DiscoveryObjects[j]; if (val2 != null && val2.IsValid() && ProcessorPrefabs.TryGetValue(val2.GetPrefab(), out var value) && !((Object)(object)value == (Object)null) && SeenStations.Add(val2.m_uid)) { num2++; try { ProcessStation(value, val2, instance); } catch (Exception ex) { instance.LogAutoProcessError("Dedicated-server processor pass failed: " + ex.Message); } } } } } DiscoveryObjects.Clear(); DiscoverySectorKeys.Clear(); if (realtimeSinceStartup >= nextDiscoveryLog) { nextDiscoveryLog = realtimeSinceStartup + 10f; instance.LogAutoProcessDiscovery(peerCount, num, num2); } } internal static void ProcessSmelter(Smelter smelter) { Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)smelter == (Object)null || !Plugin.IsServer() || !instance.AutoProcessEnabledValue || !EnsurePrefabMaps()) { return; } ZNetView stationNetView = GetStationNetView(smelter); if (!((Object)(object)stationNetView == (Object)null) && stationNetView.IsValid()) { ZDO zDO = stationNetView.GetZDO(); if (zDO != null && zDO.IsValid()) { ProcessStation(smelter, zDO, instance); } } } private static void ProcessStation(Smelter smelter, ZDO stationZdo, Plugin plugin) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)smelter == (Object)null || stationZdo == null || (Object)(object)plugin == (Object)null) { return; } try { int prefab = stationZdo.GetPrefab(); if (LoggedProcessorPrefabs.Add(prefab)) { plugin.LogAutoProcessStation(smelter, prefab); } } catch { } float autoProcessRangeValue = plugin.AutoProcessRangeValue; if (autoProcessRangeValue <= 0f) { return; } long stationCreator = stationZdo.GetLong(ZDOVars.s_creator, 0L); BuildNearbyList(stationZdo.GetPosition(), autoProcessRangeValue, stationCreator); if (Nearby.Count == 0) { LogWaitRateLimited(plugin, stationZdo, "no eligible buildable source chest within " + autoProcessRangeValue.ToString("0.#") + "m"); return; } long owner = stationZdo.GetOwner(); if (!OwnerAutomationBridge.CanRun(owner)) { LogWaitRateLimited(plugin, stationZdo, "waiting for updated QoL on the processor owner; no items removed"); return; } List<ZDOID> list = new List<ZDOID>(); int num = 0; for (int i = 0; i < Nearby.Count; i++) { if (list.Count >= 64) { break; } ZDO val = Nearby[i]; if (val.GetOwner() == owner) { list.Add(val.m_uid); } else if (num < 2 && RequestHandoff(stationZdo, val, autoProcessRangeValue, plugin)) { num++; } } if (list.Count == 0) { LogWaitRateLimited(plugin, stationZdo, "waiting for a closed source chest handoff; updated QoL and loaded station/chest required on both owners; no items removed"); return; } ZPackage val2 = new ZPackage(); val2.Write(1); val2.Write(stationZdo.m_uid); val2.Write(autoProcessRangeValue); val2.Write(plugin.MaxFuelTransfersPerTickValue); val2.Write(plugin.MaxOreTransfersPerTickValue); val2.Write(plugin.LeaveAtLeastFuelValue); val2.Write(plugin.LeaveAtLeastOreValue); val2.Write(list.Count); for (int j = 0; j < list.Count; j++) { val2.Write(list[j]); } OwnerAutomationBridge.Dispatch(stationZdo, val2); } private static bool OwnerCanLoad(long owner, ZDO station, ZDO chest) { //IL_001b: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (owner == ZDOMan.GetSessionID()) { if ((Object)(object)ZNetScene.instance != (Object)null && (Object)(object)ZNetScene.instance.FindInstance(station.m_uid) != (Object)null) { return (Object)(object)ZNetScene.instance.FindInstance(chest.m_uid) != (Object)null; } return false; } ZNetPeer val = OwnerAutomationBridge.FindPeer(owner); if (val != null && val.IsReady() && ZNetScene.InActiveArea(station.GetPosition(), val.GetRefPos())) { return ZNetScene.InActiveArea(chest.GetPosition(), val.GetRefPos()); } return false; } private static bool RequestHandoff(ZDO station, ZDO chest, float range, Plugin plugin) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) long owner = station.GetOwner(); long owner2 = chest.GetOwner(); if (!OwnerAutomationBridge.CanHandoff(owner2) || !OwnerAutomationBridge.CanHandoff(owner) || !OwnerCanLoad(owner2, station, chest) || !OwnerCanLoad(owner, station, chest)) { return false; } if (Math.Ceiling(station.GetFloat(ZDOVars.s_fuel, 0f)) >= (double)ProcessorPrefabs[station.GetPrefab()].m_maxFuel && station.GetInt(ZDOVars.s_queued, 0) >= ProcessorPrefabs[station.GetPrefab()].m_maxOre) { return false; } long ticks = ZNet.instance.GetTime().Ticks; if (Handoffs.TryGetValue(chest.m_uid, out var value) && !StoreLease.CanDispatch(ticks, value.Deadline)) { return false; } if (nextHandoffToken == int.MaxValue) { return false; } long num = OwnerAutomationBridge.FindPeer(owner)?.m_playerID ?? 0; Handoff handoff = new Handoff(); handoff.Token = ++nextHandoffToken; handoff.Owner = owner2; handoff.Deadline = ticks + 100000000; handoff.Station = station.m_uid; Handoff handoff2 = handoff; Handoffs[chest.m_uid] = handoff2; ZPackage val = new ZPackage(); val.Write(station.m_uid); val.Write(chest.m_uid); val.Write(handoff2.Token); val.Write(handoff2.Deadline); val.Write(owner); val.Write(num); val.Write(range); val.Write(plugin.LeaveAtLeastFuelValue); val.Write(plugin.LeaveAtLeastOreValue); if (OwnerAutomationBridge.DispatchHandoff(owner2, val)) { return true; } handoff2.Deadline = 0L; return false; } internal static void OnHandoffResult(long sender, ZPackage result) { //IL_0020: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IsServer() || (Object)(object)Plugin.Instance == (Object)null || result == null) { return; } try { result.SetPos(0); ZDOID val = result.ReadZDOID(); int reportedToken = result.ReadInt(); string text = result.ReadString(); if (Handoffs.TryGetValue(val, out var value) && StoreLease.Matches(value.Token, value.Owner, reportedToken, sender)) { ZDO val2 = ((ZDOMan.instance == null) ? null : ZDOMan.instance.GetZDO(value.Station)); if (val2 != null) { LogWaitRateLimited(Plugin.Instance, val2, string.Concat("source chest ", val, " handoff=", text)); } } } catch (Exception ex) { Plugin.Instance.LogAutoProcessError("Invalid chest handoff result: " + ex.Message); } } private static void BuildNearbyList(Vector3 stationPosition, float range, long stationCreator) { //IL_0029: 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) //IL_0035: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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) Nearby.Clear(); SectorObjects.Clear(); if (ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } Vector2s zone = ZoneSystem.GetZone(stationPosition); ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(1, 0, false), SectorObjects, (List<ZDO>)null); float num = range * range; for (int i = 0; i < SectorObjects.Count; i++) { ZDO val = SectorObjects[i]; if (val == null || !val.IsValid() || !BuildableContainerPrefabs.TryGetValue(val.GetPrefab(), out var value) || (Object)(object)value == (Object)null || val.GetInt(ZDOVars.s_inUse, 0) != 0 || val.GetBool("RHSQOL_RustyBackpack", false) || val.GetBool("RHSQOL_RustyBackpack_Grave", false)) { continue; } Vector3 val2 = val.GetPosition() - stationPosition; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { long chestCreator = val.GetLong(ZDOVars.s_creator, 0L); if (CanUseContainer(value, stationCreator, chestCreator)) { Nearby.Add(val); } } } SectorObjects.Clear(); } private static bool CanUseContainer(Container prefab, long stationCreator, long chestCreator) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return false; } if ((int)prefab.m_privacy == 0) { if (stationCreator != 0) { return chestCreator == stationCreator; } return false; } return true; } private static bool EnsurePrefabMaps() { if (prefabMapsReady) { return true; } if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null || ZNetScene.instance.m_prefabs.Count == 0) { return false; } if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items == null || ObjectDB.instance.m_items.Count == 0) { return false; } ProcessorPrefabs.Clear(); BuildableContainerPrefabs.Clear(); for (int i = 0; i < ZNetScene.instance.m_prefabs.Count; i++) { GameObject val = ZNetScene.instance.m_prefabs[i]; if ((Object)(object)val == (Object)null) { continue; } Smelter val2 = val.GetComponent<Smelter>(); if ((Object)(object)val2 == (Object)null) { val2 = val.GetComponentInChildren<Smelter>(); } if (!((Object)(object)val2 == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name); if (!ProcessorPrefabs.ContainsKey(stableHashCode)) { ProcessorPrefabs.Add(stableHashCode, val2); } } } for (int j = 0; j < ObjectDB.instance.m_items.Count; j++) { GameObject val3 = ObjectDB.instance.m_items[j]; if ((Object)(object)val3 == (Object)null) { continue; } ItemDrop component = val3.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces; if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null) { continue; } for (int k = 0; k < buildPieces.m_pieces.Count; k++) { GameObject val4 = buildPieces.m_pieces[k]; if ((Object)(object)val4 == (Object)null) { continue; } Container val5 = val4.GetComponent<Container>(); if ((Object)(object)val5 == (Object)null) { val5 = val4.GetComponentInChildren<Container>(); } if ((Object)(object)val5 == (Object)null || (Object)(object)val5.m_wagon != (Object)null || val5.m_autoDestroyEmpty) { continue; } string text = ((((Object)val4).name == null) ? "" : ((Object)val4).name); if (text.IndexOf("private", StringComparison.OrdinalIgnoreCase) < 0) { int stableHashCode2 = StringExtensionMethods.GetStableHashCode(text); if (!BuildableContainerPrefabs.ContainsKey(stableHashCode2)) { BuildableContainerPrefabs.Add(stableHashCode2, val5); } } } } prefabMapsReady = ProcessorPrefabs.Count > 0 && BuildableContainerPrefabs.Count > 0; if (prefabMapsReady && !registryLogged) { registryLogged = true; Plugin instance = Plugin.Instance; if ((Object)(object)instance != (Object)null) { instance.LogAutoProcessRegistry(ProcessorPrefabs.Count, BuildableContainerPrefabs.Count); } } return prefabMapsReady; } private static void LogWaitRateLimited(Plugin plugin, ZDO stationZdo, string reason) { //IL_0019: 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) if (!((Object)(object)plugin == (Object)null) && stationZdo != null) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!LastWaitLog.TryGetValue(stationZdo.m_uid, out var value) || !(realtimeSinceStartup - value < 10f)) { LastWaitLog[stationZdo.m_uid] = realtimeSinceStartup; plugin.LogAutoProcessWait(stationZdo, reason); } } } private static ZNetView GetStationNetView(Smelter smelter) { if ((Object)(object)smelter == (Object)null) { return null; } ZNetView val = null; try { val = ((Component)smelter).GetComponent<ZNetView>(); if ((Object)(object)val == (Object)null) { val = ((Component)smelter).GetComponentInParent<ZNetView>(); } } catch { } return val; } } internal static class AutoStoreModule { private sealed class DropEntry { internal ZDOID Id; internal float RegisteredAt; internal float EarliestAttempt; internal int OwnerCursor; internal int PendingToken; internal long PendingOwner; internal long PendingDeadline; } private sealed class ChestSectorCacheEntry { internal float ExpiresAt; internal readonly List<ZDOID> ChestIds = new List<ZDOID>(); } private static readonly List<DropEntry> Drops = new List<DropEntry>(); private static readonly Dictionary<int, ItemDrop> ItemPrefabs = new Dictionary<int, ItemDrop>(); private static readonly Dictionary<int, Container> BuildableContainerPrefabs = new Dictionary<int, Container>(); private static readonly List<ZDO> SectorObjects = new List<ZDO>(); private static readonly Dictionary<string, float> LastWaitLogByItem = new Dictionary<string, float>(); private static readonly Dictionary<long, ChestSectorCacheEntry> ChestSectorCache = new Dictionary<long, ChestSectorCacheEntry>(); private static readonly HashSet<long> DiscoverySectorKeys = new HashSet<long>(); private static float nextTick; private static float nextDiscovery; private static float nextDiscoveryLog; private static float nextPrune; private static int cursor; private static bool prefabMapsReady; private static bool registryLogged; private static int nextToken; internal static void Clear() { Drops.Clear(); ItemPrefabs.Clear(); BuildableContainerPrefabs.Clear(); SectorObjects.Clear(); LastWaitLogByItem.Clear(); ChestSectorCache.Clear(); DiscoverySectorKeys.Clear(); nextTick = 0f; nextDiscovery = 0f; nextDiscoveryLog = 0f; nextPrune = 0f; cursor = 0; prefabMapsReady = false; registryLogged = false; nextToken = 0; } internal static void ObserveZdo(ZDO zdo) { if (zdo != null && EnsurePrefabMaps() && ItemPrefabs.ContainsKey(zdo.GetPrefab())) { RegisterDrop(zdo); } } internal static void RegisterDrop(ItemDrop drop) { if ((Object)(object)drop == (Object)null) { return; } try { ZNetView component = ((Component)drop).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ObserveZdo(component.GetZDO()); } } catch { } } private static void RegisterDrop(ZDO zdo) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_003d: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || !zdo.IsValid() || !IsRecentGroundDrop(zdo)) { return; } ZDOID uid = zdo.m_uid; for (int i = 0; i < Drops.Count; i++) { if (Drops[i] != null && Drops[i].Id == uid) { return; } } float realtimeSinceStartup = Time.realtimeSinceStartup; DropEntry dropEntry = new DropEntry(); dropEntry.Id = uid; dropEntry.RegisteredAt = realtimeSinceStartup; dropEntry.EarliestAttempt = realtimeSinceStartup + 1f; Drops.Add(dropEntry); } internal static void Tick() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null || !Plugin.IsServer() || !instance.AutoStoreEnabledValue || !EnsurePrefabMaps()) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= nextDiscovery) { nextDiscovery = realtimeSinceStartup + 8f; DiscoverNearbyDrops(); } if (realtimeSinceStartup < nextTick) { return; } nextTick = realtimeSinceStartup + 0.5f; Prune(realtimeSinceStartup); if (Drops.Count == 0) { return; } int num = instance.AutoStoreMaxDropsPerTickValue; if (num > Drops.Count) { num = Drops.Count; } int count = Drops.Count; int num2 = 0; int num3 = 0; long now = (((Object)(object)ZNet.instance == (Object)null) ? 0 : ZNet.instance.GetTime().Ticks); while (num2 < count && num3 < num && Drops.Count > 0) { if (cursor >= Drops.Count) { cursor = 0; } DropEntry dropEntry = Drops[cursor]; cursor++; num2++; if (dropEntry == null || realtimeSinceStartup < dropEntry.EarliestAttempt || !StoreLease.CanDispatch(now, dropEntry.PendingDeadline)) { continue; } ZDO val = ((ZDOMan.instance == null) ? null : ZDOMan.instance.GetZDO(dropEntry.Id)); if (val == null || !val.IsValid() || !HasActiveStoreClient(val)) { continue; } num3++; bool flag = false; try { flag = TryStore(dropEntry, val, instance, realtimeSinceStartup); } catch (Exception ex) { instance.LogAutoStoreError("Ground-drop transfer failed: " + ex.Message); } if (flag) { int num4 = Drops.IndexOf(dropEntry); if (num4 >= 0) { if (num4 < cursor) { cursor--; } Drops.RemoveAt(num4); if (cursor < 0) { cursor = 0; } } } else { dropEntry.EarliestAttempt = Math.Max(dropEntry.EarliestAttempt, realtimeSinceStartup + 1f); } } } private static bool HasActiveStoreClient(ZDO drop) { if (CanOwnerLoad(drop, ZDOMan.GetSessionID())) { return true; } if ((Object)(object)ZNet.instance == (Object)null) { return false; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); if (peers == null) { return false; } for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val != null && OwnerAutomationBridge.CanStore(val.m_uid) && CanOwnerLoad(drop, val.m_uid)) { return true; } } return false; } private static bool CanOwnerLoad(ZDO zdo, long owner) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (zdo == null) { return false; } if (owner == ZDOMan.GetSessionID()) { if ((Object)(object)ZNetScene.instance != (Object)null) { return (Object)(object)ZNetScene.instance.FindInstance(zdo.m_uid) != (Object)null; } return false; } ZNetPeer val = OwnerAutomationBridge.FindPeer(owner); if (val != null && val.IsReady()) { return ZNetScene.InActiveArea(zdo.GetPosition(), val.GetRefPos()); } return false; } private static bool EnsurePrefabMaps() { if (prefabMapsReady) { return true; } if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null || ZNetScene.instance.m_prefabs.Count == 0) { return false; } if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items == null || ObjectDB.instance.m_items.Count == 0) { return false; } ItemPrefabs.Clear(); BuildableContainerPrefabs.Clear(); for (int i = 0; i < ZNetScene.instance.m_prefabs.Count; i++) { GameObject val = ZNetScene.instance.m_prefabs[i]; if (!((Object)(object)val == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name); ItemDrop val2 = val.GetComponent<ItemDrop>(); if ((Object)(object)val2 == (Object)null) { val2 = val.GetComponentInChildren<ItemDrop>(); } if ((Object)(object)val2 != (Object)null && !ItemPrefabs.ContainsKey(stableHashCode)) { ItemPrefabs.Add(stableHashCode, val2); } } } for (int j = 0; j < ObjectDB.instance.m_items.Count; j++) { GameObject val3 = ObjectDB.instance.m_items[j]; if ((Object)(object)val3 == (Object)null) { continue; } ItemDrop component = val3.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces; if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null) { continue; } for (int k = 0; k < buildPieces.m_pieces.Count; k++) { GameObject val4 = buildPieces.m_pieces[k]; if ((Object)(object)val4 == (Object)null) { continue; } Container val5 = val4.GetComponent<Container>(); if ((Object)(object)val5 == (Object)null) { val5 = val4.GetComponentInChildren<Container>(); } if ((Object)(object)val5 == (Object)null || (Object)(object)val5.m_wagon != (Object)null || val5.m_autoDestroyEmpty) { continue; } string text = ((((Object)val4).name == null) ? "" : ((Object)val4).name); if (text.IndexOf("private", StringComparison.OrdinalIgnoreCase) < 0) { int stableHashCode2 = StringExtensionMethods.GetStableHashCode(text); if (!BuildableContainerPrefabs.ContainsKey(stableHashCode2)) { BuildableContainerPrefabs.Add(stableHashCode2, val5); } } } } if (BuildableContainerPrefabs.Count == 0) { for (int l = 0; l < ZNetScene.instance.m_prefabs.Count; l++) { GameObject val6 = ZNetScene.instance.m_prefabs[l]; if ((Object)(object)val6 == (Object)null) { continue; } Piece val7 = val6.GetComponent<Piece>(); if ((Object)(object)val7 == (Object)null) { val7 = val6.GetComponentInChildren<Piece>(); } if ((Object)(object)val7 == (Object)null) { continue; } Container val8 = val6.GetComponent<Container>(); if ((Object)(object)val8 == (Object)null) { val8 = val6.GetComponentInChildren<Container>(); } if ((Object)(object)val8 == (Object)null || (Object)(object)val8.m_wagon != (Object)null || val8.m_autoDestroyEmpty) { continue; } string text2 = ((((Object)val6).name == null) ? "" : ((Object)val6).name); if (text2.IndexOf("private", StringComparison.OrdinalIgnoreCase) < 0) { int stableHashCode3 = StringExtensionMethods.GetStableHashCode(text2); if (!BuildableContainerPrefabs.ContainsKey(stableHashCode3)) { BuildableContainerPrefabs.Add(stableHashCode3, val8); } } } } prefabMapsReady = ItemPrefabs.Count > 0 && BuildableContainerPrefabs.Count > 0; if (prefabMapsReady && !registryLogged) { registryLogged = true; Plugin instance = Plugin.Instance; if ((Object)(object)instance != (Object)null) { instance.LogAutoStoreRegistry(ItemPrefabs.Count, BuildableContainerPrefabs.Count); } } return prefabMapsReady; } private static void DiscoverNearbyDrops() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); int peerCount = peers?.Count ?? 0; int num = 0; int num2 = 0; DiscoverySectorKeys.Clear(); if (peers != null) { for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val == null) { continue; } Vector2s zone = ZoneSystem.GetZone(val.m_refPos); long item = SectorKey(zone); if (!DiscoverySectorKeys.Add(item)) { continue; } SectorObjects.Clear(); ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(1, 0, false), SectorObjects, (List<ZDO>)null); num += SectorObjects.Count; for (int j = 0; j < SectorObjects.Count; j++) { ZDO val2 = SectorObjects[j]; if (val2 != null && val2.IsValid() && ItemPrefabs.ContainsKey(val2.GetPrefab())) { num2++; RegisterDrop(val2); } } } } SectorObjects.Clear(); DiscoverySectorKeys.Clear(); float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= nextDiscoveryLog) { nextDiscoveryLog = realtimeSinceStartup + 10f; Plugin instance = Plugin.Instance; if ((Object)(object)instance != (Object)null) { instance.LogAutoStoreDiscovery(peerCount, num, num2, Drops.Count); } } } private static bool TryStore(DropEntry entry, ZDO dropZdo, Plugin plugin, float now) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Invalid comparison between Unknown and I4 //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) if (entry == null || dropZdo == null || (Object)(object)plugin == (Object)null) { return false; } long num = (((Object)(object)ZNet.instance == (Object)null) ? 0 : ZNet.instance.GetTime().Ticks); if (!StoreLease.CanDispatch(num, entry.PendingDeadline)) { return false; } if (!ItemPrefabs.TryGetValue(dropZdo.GetPrefab(), out var value) || (Object)(object)value == (Object)null) { return false; } ItemData val = LoadItemData(value, dropZdo); if (val == null || val.m_shared == null) { return false; } bool isPiece = dropZdo.GetBool(ZDOVars.s_piece, false); bool isConsumable = (int)val.m_shared.m_itemType == 2; if (!ServerQoLRules.ShouldAutoStoreItem(plugin.AutoStoreEnabledValue, autoPickup: true, isPiece, val.m_shared.m_maxStackSize, isConsumable)) { return false; } int stack = val.m_stack; if (stack <= 0) { return false; } Vector3 position = dropZdo.GetPosition(); float autoStoreMinPlayerDistanceValue = plugin.AutoStoreMinPlayerDistanceValue; bool playerInRange = autoStoreMinPlayerDistanceValue > 0f && IsAnyPeerInRange(position, autoStoreMinPlayerDistanceValue); float ageSeconds = now - entry.RegisteredAt; if (ServerQoLRules.IsPlayerProtectionActive(ageSeconds, plugin.AutoStorePlayerProtectionSecondsValue, playerInRange)) { return false; } if (!FindTargetDirect(entry, dropZdo, position, plugin.AutoStoreRangeValue, out var owner, out var candidates, out var diagnostic)) { LogWaitRateLimited(plugin, val.m_shared.m_name, diagnostic, now); return false; } if (nextToken == int.MaxValue) { nextToken = 0; } entry.PendingToken = ++nextToken; entry.PendingOwner = owner; entry.PendingDeadline = num + 100000000; ZPackage val2 = new ZPackage(); val2.Write(dropZdo.m_uid); val2.Write(entry.PendingToken); val2.Write(entry.PendingDeadline); val2.Write(plugin.AutoStoreRangeValue); val2.Write(candidates.Count); foreach (ZDOID item in candidates) { val2.Write(item); } if (!OwnerAutomationBridge.DispatchStore(owner, val2)) { entry.PendingDeadline = 0L; LogWaitRateLimited(plugin, val.m_shared.m_name, "waiting for a connected AutoStore v3 chest owner", now); } entry.EarliestAttempt = now + 1f; return false; } private static bool FindTargetDirect(DropEntry entry, ZDO drop, Vector3 position, float range, out long owner, out List<ZDOID> candidates, out string diagnostic) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) //IL_00b1: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) owner = 0L; candidates = null; diagnostic = "no nearby eligible buildable chest"; if (ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null || range <= 0f) { return false; } List<ZDO> list = new List<ZDO>(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (ZDOID cachedChestId in GetCachedChestIds(ZoneSystem.GetZone(position), Time.realtimeSinceStartup)) { ZDO zDO = ZDOMan.instance.GetZDO(cachedChestId); if (zDO == null || !zDO.IsValid() || !BuildableContainerPrefabs.ContainsKey(zDO.GetPrefab())) { continue; } Vector3 val = zDO.GetPosition() - position; if (((Vector3)(ref val)).sqrMagnitude > range * range) { continue; } num++; if (!zDO.GetBool("RHSQOL_RustyBackpack", false) && !zDO.GetBool("RHSQOL_RustyBackpack_Grave", false)) { if (zDO.GetInt(ZDOVars.s_inUse, 0) != 0) { num2++; } else if (!OwnerAutomationBridge.CanStore(zDO.GetOwner())) { num3++; } else if (!CanOwnerLoad(drop, zDO.GetOwner()) || !CanOwnerLoad(zDO, zDO.GetOwner())) { num4++; } else { list.Add(zDO); } } } list.Sort(delegate(ZDO a, ZDO b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_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_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = a.GetPosition() - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; Vector3 val3 = b.GetPosition() - position; return sqrMagnitude.CompareTo(((Vector3)(ref val3)).sqrMagnitude); }); List<long> list2 = new List<long>(); foreach (ZDO item in list) { if (item.GetOwner() == drop.GetOwner()) { list2.Add(drop.GetOwner()); break; } } foreach (ZDO item2 in list) { if (!list2.Contains(item2.GetOwner())) { list2.Add(item2.GetOwner()); } } if (list2.Count == 0) { diagnostic = "nearbyChests=" + num + " openChests=" + num2 + " ownersWithoutAutoStoreV3=" + num3 + " ownersOutsideLoadedArea=" + num4 + " range=" + range.ToString("0.#") + "m"; return false; } owner = list2[entry.OwnerCursor % list2.Count]; entry.OwnerCursor = (entry.OwnerCursor + 1) % list2.Count; candidates = new List<ZDOID>(); foreach (ZDO item3 in list) { if (item3.GetOwner() == owner && candidates.Count < 64) { candidates.Add(item3.m_uid); } } return candidates.Count > 0; } internal static void OnResult(long sender, ZPackage result) { //IL_0029: 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_0049: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IsServer() || result == null || (Object)(object)ZNet.instance == (Object)null) { return; } try { result.SetPos(0); ZDOID dropId = result.ReadZDOID(); int reportedToken = result.ReadInt(); string text = result.ReadString(); int num = result.ReadInt(); ZDOID val = result.ReadZDOID(); DropEntry dropEntry = Drops.Find((DropEntry d) => d != null && d.Id == dropId); if (dropEntry != null && StoreLease.Matches(dropEntry.PendingToken, dropEntry.PendingOwner, reportedToken, sender)) { if (text == "stored" && num > 0) { Plugin.Instance.LogOwnerAutomation(string.Concat("STORED live-owner drop=", dropId, " count=", num, " chest=", val)); dropEntry.EarliestAttempt = Math.Max(dropEntry.EarliestAttempt, Time.realtimeSinceStartup + 10f); } else { LogWaitRateLimited(Plugin.Instance, ((object)Unsafe.As<ZDOID, ZDOID>(ref dropId)/*cast due to .constrained prefix*/).ToString(), text + "; chestOwner=" + sender, Time.realtimeSinceStartup); } } } catch (Exception ex) { if ((Object)(object)Plugin.Instance != (Object)null) { Plugin.Instance.LogAutoStoreError("Invalid owner result: " + ex.Message); } } } private static long SectorKey(Vector2s sector) { return ((long)sector.x << 32) ^ (uint)sector.y; } private static List<ZDOID> GetCachedChestIds(Vector2s sector, float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) long key = SectorKey(sector); if (ChestSectorCache.TryGetValue(key, out var value) && value != null && now < value.ExpiresAt) { return value.ChestIds; } if (value == null) { value = new ChestSectorCacheEntry(); } if (ChestSectorCache.Count > 256) { ChestSectorCache.Clear(); } value.ChestIds.Clear(); SectorObjects.Clear(); ZDOMan.instance.FindSectorObjects(sector, new SimulationDistance(1, 0, false), SectorObjects, (List<ZDO>)null); for (int i = 0; i < SectorObjects.Count; i++) { ZDO val = SectorObjects[i]; if (val != null && val.IsValid() && BuildableContainerPrefabs.ContainsKey(val.GetPrefab())) { value.ChestIds.Add(val.m_uid); } } SectorObjects.Clear(); value.ExpiresAt = now + 2f; ChestSectorCache[key] = value; return value.ChestIds; } private static bool IsRecentGroundDrop(ZDO zdo) { if (zdo == null) { return false; } try { long num = zdo.GetLong(ZDOVars.s_spawnTime, 0L); if (num <= 0 || (Object)(object)ZNet.instance == (Object)null) { return true; } DateTime dateTime = new DateTime(num); double totalSeconds = (ZNet.instance.GetTime() - dateTime).TotalSeconds; if (totalSeconds < 0.0) { return true; } return totalSeconds <= 120.0; } catch { return true; } } private static bool IsAnyPeerInRange(Vector3 position, float range) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) if (range <= 0f || (Object)(object)ZNet.instance == (Object)null) { return false; } List<ZNetPeer> peers = ZNet.instance.GetPeers(); if (peers == null || peers.Count == 0) { return false; } float num = range * range; for (int i = 0; i < peers.Count; i++) { ZNetPeer val = peers[i]; if (val != null) { Vector3 val2 = val.m_refPos - position; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } return false; } private static void LogWaitRateLimited(Plugin plugin, string itemName, string reason, float now) { if (!((Object)(object)plugin == (Object)null)) { string text = (string.IsNullOrEmpty(itemName) ? "unknown" : itemName); if (!LastWaitLogByItem.TryGetValue(text, out var value) || !(now - value < 20f)) { LastWaitLogByItem[text] = now; plugin.LogAutoStoreWait(text, reason); } } } private static ItemData LoadItemData(ItemDrop prefab, ZDO zdo) { if ((Object)(object)prefab == (Object)null || prefab.m_itemData == null || zdo == null) { return null; } try { ItemData val = prefab.m_itemData.Clone(); val.m_dropPrefab = ((Component)prefab).gameObject; ItemDrop.LoadFromZDO(val, zdo, -1); return val; } catch { return null; } } private static void Prune(float now) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (now < nextPrune) { return; } nextPrune = now + 10f; if (ZDOMan.instance == null) { Drops.Clear(); cursor = 0; return; } for (int num = Drops.Count - 1; num >= 0; num--) { DropEntry dropEntry = Drops[num]; if (dropEntry == null || ZDOMan.instance.GetZDO(dropEntry.Id) == null) { Drops.RemoveAt(num); } } if (cursor > Drops.Count) { cursor = 0; } } } [HarmonyPatch(typeof(ZDO), "Deserialize")] internal static class AutoStoreZdoDeserializePatch { private static void Postfix(ZDO __instance) { if (Plugin.IsServer()) { AutoStoreModule.ObserveZdo(__instance); } } } [HarmonyPatch(typeof(ItemDrop), "Awake")] internal static class AutoStoreItemDropAwakePatch { private static void Postfix(ItemDrop __instance) { AutoStoreModule.RegisterDrop(__instance); } } [HarmonyPatch(typeof(ItemDrop), "Start")] internal static class AutoStoreItemDropStartPatch { private static void Postfix(ItemDrop __instance) { AutoStoreModule.RegisterDrop(__instance); } } } namespace RustyHeathens.Backpacks { internal sealed class BackpackDeathLocation { internal Vector3 DeathPoint; internal ZDOID GraveId = ZDOID.None; internal Vector3 GravePoint; } internal enum DeathLocationRead { Legacy, Valid, Invalid } internal static class BackpackDeathPlacement { internal const string AnchorKey = "RHSQOL_RustyBackpack_DeathAnchor"; internal const float GraveSpacing = 1.25f; private const int WireMarker = 1380467249; internal static bool Finite(Vector3 point) { if (Coordinate(point.x) && Coordinate(point.y)) { return Coordinate(point.z); } return false; } private static bool Coordinate(float value) { if (!float.IsNaN(value) && !float.IsInfinity(value)) { return Math.Abs(value) < 100000f; } return false; } internal static Vector3 Beside(Vector3 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) return point + Vector3.right * 1.25f; } internal static void Write(ZPackage report, ZDOID character, BackpackDeathLocation location) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) report.Write(1380467249); report.Write(character); report.Write(location.DeathPoint); report.Write(location.GraveId); report.Write(location.GravePoint); } internal static DeathLocationRead Read(ZPackage report, ZDOID character, out BackpackDeathLocation location) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0055: 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_0070: 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) //IL_009b: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) location = null; if (report.GetPos() == report.Size()) { return DeathLocationRead.Legacy; } try { if (report.ReadInt() != 1380467249 || report.ReadZDOID() != character) { return DeathLocationRead.Invalid; } BackpackDeathLocation backpackDeathLocation = new BackpackDeathLocation(); backpackDeathLocation.DeathPoint = report.ReadVector3(); backpackDeathLocation.GraveId = report.ReadZDOID(); backpackDeathLocation.GravePoint = report.ReadVector3(); BackpackDeathLocation backpackDeathLocation2 = backpackDeathLocation; if (report.GetPos() != report.Size() || !Finite(backpackDeathLocation2.DeathPoint) || !Finite(backpackDeathLocation2.GravePoint)) { return DeathLocationRead.Invalid; } if (!((ZDOID)(ref backpackDeathLocation2.GraveId)).IsNone()) { Vector3 val = backpackDeathLocation2.GravePoint - backpackDeathLocation2.DeathPoint; if (((Vector3)(ref val)).sqrMagnitude > 16f) { return DeathLocationRead.Invalid; } } location = backpackDeathLocation2; return DeathLocationRead.Valid; } catch { return DeathLocationRead.Invalid; } } internal static bool IsInventoryGrave(ZDO grave, long playerId) { if (grave != null && grave.IsValid() && playerId != 0 && grave.GetPrefab() == StringExtensionMethods.GetStableHashCode("Player_tombstone") && grave.GetLong(ZDOVars.s_owner, 0L) == playerId && !grave.GetBool("RHSQOL_RustyBackpack_Grave", false)) { return !grave.GetString(ZDOVars.s_ownerName, "").EndsWith(" - Rusty Backpack", StringComparison.Ordinal); } return false; } internal static Vector3 Resolve(BackpackDeathLocation location, Vector3 frozenDeathPoint, ZDO grave, long playerId, out ZDOID anchor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) //IL_001f: 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_0079: Unknown result type (might be due to invalid IL or missing references) //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_0029: 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) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) anchor = ZDOID.None; if (location == null) { return frozenDeathPoint; } if (((ZDOID)(ref location.GraveId)).IsNone()) { return location.DeathPoint; } if (grave != null) { if (grave.m_uid != location.GraveId || !IsInventoryGrave(grave, playerId) || !Finite(grave.GetPosition())) { return location.DeathPoint; } anchor = grave.m_uid; return Beside(grave.GetPosition()); } anchor = location.GraveId; return Beside(location.GravePoint); } } } namespace RustyHeathens.ServerQoL { internal static class BackpackModule { private sealed class DedicatedPlayerState { internal long PeerId; internal long PlayerId; internal ZDOID CharacterId = ZDOID.None; internal ZDOID BackpackId = ZDOID.None; internal int LastEmoteId = int.MinValue; internal bool LastDead; internal float OpenAt = -1f; internal int OpenAttemptsRemaining; internal float NextMaintenance; internal float PendingDeathAt = -1f; internal byte[] DeathSnapshot; internal ZDOID DeathSnapshotId = ZDOID.None; internal float NextAssigned; internal bool DeathConfirmed; internal bool HasDeathPoint; internal Vector3 DeathPoint; internal BackpackDeathLocation DeathLocation; } internal const string ArgusBackpackGuid = "ArgusMagnus.ServersideQoL.Backpack"; internal const string ClientOpenRpc = "RHSQOL_BackpackOpen_v1"; internal const string ClientAssignedRpc = "RHSQOL_BackpackAssigned_v2"; internal const string RequestRpc = "RHSQOL_BackpackRequest_v2"; internal const string DeathRpc = "RHSQOL_BackpackDeath_v2"; private static readonly int MarkerKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack"); private static readonly int PlayerKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Player"); private static readonly int SlotsKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Slots"); private static readonly int CanonicalKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Canonical"); private static readonly int ArchivedKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Archived"); private static readonly List<ZDO> SearchZdos = new List<ZDO>(); private static readonly string[] BossKeys = new string[7] { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader" }; private static Container backpack; private static GameObject backpackObject; private static ZDOID backpackId = ZDOID.None; private static float openAt = -1f; private static float nextMaintenance; private static long lastPlayerId; private static long lastWorldUid; private static bool argusWarningLogged; private static readonly Dictionary<long, DedicatedPlayerState> DedicatedStates = new Dictionary<long, DedicatedPlayerState>(); private static readonly HashSet<long> SeenDedicatedPeers = new HashSet<long>(); private static float nextDedicatedTick; private static readonly Dictionary<long, ZDOID> CanonicalBackpacks = new Dictionary<long, ZDOID>(); private static readonly HashSet<long> DuplicateWarnings = new HashSet<long>(); private static bool globalLookupFailed; internal static bool ArgusBackpackPresent { get { if (Chainloader.PluginInfos != null) { return Chainloader.PluginInfos.ContainsKey("ArgusMagnus.ServersideQoL.Backpack"); } return false; } } internal static void Clear() { //IL_000c: 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) backpack = null; backpackObject = null; backpackId = ZDOID.None; openAt = -1f; nextMaintenance = 0f; lastPlayerId = 0L; lastWorldUid = 0L; argusWarningLogged = false; nextDedicatedTick = 0f; DedicatedStates.Clear(); CanonicalBackpacks.Clear(); DuplicateWarnings.Clear(); SeenDedicatedPeers.Clear(); SearchZdos.Clear(); } internal static void RegisterRpc() { ZRoutedRpc.instance.Register<string>("RHSQOL_BackpackRequest_v2", (Action<long, string>)OnClientRequest); ZRoutedRpc.instance.Register<ZPackage>("RHSQOL_BackpackDeath_v2", (Action<long, ZPackage>)OnDeathSnapshot); } private static DedicatedPlayerState StateFor(ZNetPeer peer, ZDO player) { //IL_0046: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) long num = player.GetLong(ZDOVars.s_playerID, 0L); if (!DedicatedStates.TryGetValue(peer.m_uid, out var value) || value.PlayerId != num) { DedicatedPlayerState dedicatedPlayerState = new DedicatedPlayerState(); dedicatedPlayerState.PeerId = peer.m_uid; dedicatedPlayerState.PlayerId = num; dedicatedPlayerState.CharacterId = peer.m_characterID; dedicatedPlayerState.LastEmoteId = player.GetInt(ZDOVars.s_emoteID, 0); dedicatedPlayerState.LastDead = player.GetBool(ZDOVars.s_dead, false); value = dedicatedPlayerState; DedicatedStates[peer.m_uid] = value; } value.CharacterId = peer.m_characterID; return value; } private static void OnClientRequest(long sender, string request) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if (!ActivationAllowed(instance) || !Plugin.IsServer() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } ZNetPeer val = OwnerAutomationBridge.FindPeer(sender); if (val == null || !val.IsReady() || ((ZDOID)(ref val.m_characterID)).IsNone()) { return; } ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID); if (zDO == null || zDO.GetBool(ZDOVars.s_dead, false) || zDO.GetLong(ZDOVars.s_playerID, 0L) == 0) { return; } bool flag = request == "open|" + instance.BackpackOpenEmoteValue; if (!flag && request != "resolve") { return; } DedicatedPlayerState dedicatedPlayerState = StateFor(val, zDO); if (!(dedicatedPlayerState.PendingDeathAt >= 0f) && EnsureDedicatedBackpack(dedicatedPlayerState, zDO, instance)) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RHSQOL_BackpackAssigned_v2", new object[1] { dedicatedPlayerState.BackpackId }); if (flag) { dedicatedPlayerState.OpenAttemptsRemaining = 6; dedicatedPlayerState.OpenAt = Time.realtimeSinceStartup; OpenDedicatedBackpack(dedicatedPlayerState, zDO, val, instance); } } } private static void OnDeathSnapshot(long sender, ZPackage report) { //IL_0046: 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_0074: 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) //IL_00a0: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Plugin.Instance; if (!ActivationAllowed(instance) || !Plugin.IsServer() || report == null || ZDOMan.instance == null) { return; } ZNetPeer val = OwnerAutomationBridge.FindPeer(sender); if (val == null || !val.IsReady() || ((ZDOID)(ref val.m_characterID)).IsNone()) { return; } ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID); if (zDO == null || zDO.GetLong(ZDOVars.s_playerID, 0L) == 0) { return; } DedicatedPlayerState dedicatedPlayerState = StateFor(val, zDO); ZDOID val2 = report.ReadZDOID(); byte[] array = report.ReadByteArray(); if (BackpackDeathPlacement.Read(report, val.m_characterID, out var location) == DeathLocationRead.Invalid) { instance.LogBackpackWarning("DEATH invalid or stale character location report; original backpack kept intact."); return; } ZDO zDO2 = ZDOMan.instance.GetZDO(val2); if (array != null && array.Length <= 2097152 && IsDedicatedBackpackFor(zDO2, dedicatedPlayerState.PlayerId) && (!CanonicalBackpacks.TryGetValue(dedicatedPlayerState.PlayerId, out var value) || !(value != val2)) && zDO2.GetOwner() == sender) { dedicatedPlayerState.BackpackId = val2; dedicatedPlayerState.DeathSnapshotId = val2; dedicatedPlayerState.DeathSnapshot = array; dedicatedPlayerState.DeathLocation = location; RememberDeathPoint(dedicatedPlayerState, zDO); dedicatedPlayerState.DeathConfirmed = dedicatedPlayerState.DeathConfirmed || zDO.GetBool(ZDOVars.s_dead, false); if (dedicatedPlayerState.PendingDeathAt < 0f) { dedicatedPlayerState.PendingDeathAt = Time.realtimeSinceStartup + 1f; } } } internal static bool ActivationAllowed(Plugin plugin) { if ((Object)(object)plugin == (Object)null || !plugin.BackpackEnabledValue) { return false; } if (ArgusBackpackPresent) { if (!argusWarningLogged) { argusWarningLogged = true; plugin.LogBackpackWarning("ArgusMagnus.ServersideQoL.Backpack is still loaded. Rusty Backpack is blocked to prevent two backpack systems from touching player storage. Remove the Argus Backpack add-on before using Rusty Backpack."); } return false; } return true; } internal static void Tick() { Plugin instance = Plugin.Instance; if (ActivationAllowed(instance) && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { if (ZNet.instance.IsDedicated()) { TickDedicated(instance); } else { TickLocal(instance); } } } private static void TickLocal(Plugin plugin) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } if (openAt >= 0f && Time.realtimeSinceStartup >= openAt) { openAt = -1f; OpenBackpackNow(localPlayer, plugin); } if (!(Time.realtimeSinceStartup < nextMaintenance)) { nextMaintenance = Time.realtimeSinceStartup + 1f; long playerID = localPlayer.GetPlayerID(); long worldUID = ZNet.instance.GetWorldUID(); if (playerID != lastPlayerId || worldUID != lastWorldUid) { ForgetRuntimeReference(); lastPlayerId = playerID; lastWorldUid = worldUID; } if ((Object)(object)backpackObject != (Object)null) { FollowPlayer(localPlayer); EnsureCapacity(localPlayer, plugin); } } } private static void TickDedicated(Plugin plugin) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || ZRoutedRpc.instance == null) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextDedicatedTick) { return; } nextDedicatedTick = realtimeSinceStartup + 0.1f; IList<ZNetPeer> list = new List<ZNetPeer>(ZNet.instance.GetPeers()); SeenDedicatedPeers.Clear(); for (int i = 0; i < list.Count; i++) { ZNetPeer val = list[i]; if (val == null || !val.IsReady() || val.m_uid == 0 || ((ZDOID)(ref val.m_characterID)).IsNone()) { continue; } ZDO zDO = ZDOMan.instance.GetZDO(val.m_characterID); if (zDO == null || !zDO.IsValid()) { continue; } long num = zDO.GetLong(ZDOVars.s_playerID, 0L); if (num == 0) { continue; } SeenDedicatedPeers.Add(val.m_uid); DedicatedPlayerState dedicatedPlayerState = StateFor(val, zDO); bool flag = zDO.GetBool(ZDOVars.s_dead, false); int num2 = zDO.GetInt(ZDOVars.s_emoteID, 0); if (num2 != dedicatedPlayerState.LastEmoteId) { dedicatedPlayerState.LastEmoteId = num2; string a = zDO.GetString(ZDOVars.s_emote, string.Empty); if (!flag && dedicatedPlayerState.PendingDeathAt < 0f && string.Equals(a, plugin.BackpackOpenEmoteValue, StringComparison.OrdinalIgnoreCase) && EnsureDedicatedBackpack(dedicatedPlayerState, zDO, plugin)) { dedicatedPlayerState.OpenAttemptsRemaining = 6; dedicatedPlayerState.OpenAt = realtimeSinceStartup + 0.25f; ZDO zDO2 = ZDOMan.instance.GetZDO(dedicatedPlayerState.BackpackId); if (zDO2 != null) { ZDOMan.instance.ForceSendZDO(val.m_uid, zDO2.m_uid); } } } if (flag && !dedicatedPlayerState.LastDead) { dedicatedPlayerState.DeathConfirmed = true; RememberDeathPoint(dedicatedPlayerState, zDO); if (dedicatedPlayerState.PendingDeathAt < 0f) { dedicatedPlayerState.PendingDeathAt = realtimeSinceStartup + 1f; } } dedicatedPlayerState.LastDead = flag; if (dedicatedPlayerState.PendingDeathAt >= 0f) { if (realtimeSinceStartup >= dedicatedPlayerState.PendingDeathAt && dedicatedPlayerState.DeathConfirmed) { HandleDedicatedDeath(dedicatedPlayerState, zDO, val, plugin); dedicatedPlayerState.PendingDeathAt = -1f; dedicatedPlayerState.DeathSnapshot = null; dedicatedPlayerState.DeathSnapshotId = ZDOID.None; dedicatedPlayerState.DeathConfirmed = false; dedicatedPlayerState.HasDeathPoint = false; dedicatedPlayerState.DeathLocation = null; } else { if (!(realtimeSinceStartup >= dedicatedPlayerState.PendingDeathAt + 3f)) { continue; } dedicatedPlayerState.PendingDeathAt = -1f; dedicatedPlayerState.DeathSnapshot = null; dedicatedPlayerState.DeathSnapshotId = ZDOID.None; dedicatedPlayerState.DeathConfirmed = false; dedicatedPlayerState.HasDeathPoint = false; dedicatedPlayerState.DeathLocation = null; } } if (flag) { dedicatedPlayerState.OpenAt = -1f; dedicatedPlayerState.OpenAttemptsRemaining = 0; continue; } if (dedicatedPlayerState.OpenAt >= 0f && realtimeSinceStartup >= dedicatedPlayerState.OpenAt) { OpenDedicatedBackpack(dedicatedPlayerState, zDO, val, plugin); dedicatedPlayerState.OpenAttemptsRemaining--; dedicatedPlayerState.OpenAt = ((dedicatedPlayerState.OpenAttemptsRemaining > 0) ? (realtimeSinceStartup + 0.35f) : (-1f)); } if (realtimeSinceStartup >= dedicatedPlayerState.NextMaintenance) { dedicatedPlayerState.NextMaintenance = realtimeSinceStartup + 1f; MaintainDedicatedBackpack(dedicatedPlayerState, zDO, val, plugin); } } if (DedicatedStates.Count <= SeenDedicatedPeers.Count) { return; } List<long> list2 = null; foreach (KeyValuePair<long, DedicatedPlayerState> dedicatedState in DedicatedStates) { if (!SeenDedicatedPeers.Contains(dedicatedState.Key)) { if (list2 == null) { list2 = new List<long>(); } list2.Add(dedicatedState.Key); } } if (list2 != null) { for (int j = 0; j < list2.Count; j++) { DedicatedStates.Remove(list2[j]); } } } private static bool EnsureDedicatedBackpack(DedicatedPlayerState state, ZDO playerZdo, Plugin plugin) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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) if (CanonicalBackpacks.TryGetValue(state.PlayerId, out var value)) { state.BackpackId = value; } ZDO val = (((ZDOID)(ref state.BackpackId)).IsNone() ? null : ZDOMan.instance.GetZDO(state.BackpackId)); if (val != null && val.IsValid() && !IsDedicatedBackpackFor(val, state.PlayerId)) { return false; } if (IsDedicatedBackpackFor(val, state.PlayerId)) { int desiredSlots = GetDesiredSlots(plugin); int num = val.GetInt(SlotsKey, 0); if (num < desiredSlots) { val = ResizeDedicatedBackpack(state, playerZdo, val, desiredSlots, plugin); } return val != null; } val = FindDedicatedBackpackGlobal(state.PlayerId, plugin); if (val != null) { state.BackpackId = val.m_uid; CanonicalBackpacks[state.PlayerId] = val.m_uid; int desiredSlots2 = GetDesiredSlots(plugin); int num2 = val.GetInt(SlotsKey, 0); if (num2 < desiredSlots2) { val = ResizeDedicatedBackpack(state, playerZdo, val, desiredSlots2, plugin); } return val != null; } if (globalLookupFailed) { return false; } int desiredSlots3 = GetDesiredSlots(plugin); ZDO val2 = CreateDedicatedBackpackZdo(playerZdo.GetPosition() + Vector3.down * 0.6f, state.PeerId, state.PlayerId, desiredSlots3, null, plugin); if (val2 == null) { return false; } state.BackpackId = val2.m_uid; CanonicalBackpacks[state.PlayerId] = val2.m_uid; if (plugin.VerboseLoggingValue) { plugin.LogBackpackInfo(string.Concat("CREATED dedicated backpack zdo=", val2.m_uid, " slots=", desiredSlots3, " playerId=", state.PlayerId, ".")); } return true; } private static bool IsDedicatedBackpackFor(ZDO zdo, long playerId) { if (zdo != null && zdo.IsValid() && zdo.GetBool(MarkerKey, false) && !zdo.GetBool(ArchivedKey, false)) { return zdo.GetLong(PlayerKey, 0L) == playerId; } return false; } private static ZDO FindDedicatedBackpackGlobal(long playerId, Plugin plugin) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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) globalLookupFailed = false; try { List<ZDOID> list = new List<ZDOID>(ZDOExtraData.GetAllZDOIDsWithHash((Type)4, PlayerKey)); ZDO val = null; int num = -1; int num2 = 0; bool flag = false; List<ZDO> list2 = new List<ZDO>(); for (int i = 0; i < list.Count; i++) { ZDO zDO = ZDOMan.instance.GetZDO(list[i]); if (!IsDedicatedBackpackFor(zDO, playerId)) { continue; } num2++; list2.Add(zDO); int slots = Math.Max(1, zDO.GetInt(SlotsKey, plugin.BackpackInitialSlotsValue)); GetStoredInventorySize(zDO, slots, out var width, out var height); int num3 = 0; try { Inventory val2 = LoadInventoryFromZdo(zDO, width, height); if (val2 != null) { num3 = val2.NrOfItems(); } } catch (Exception innerException) { throw new InvalidOperationException(string.Concat("Could not read saved backpack ", zDO.m_uid, "; recovery must not create or archive storage."), innerException); } bool flag2 = zDO.GetBool(CanonicalKey, false); if (val == null || (flag2 && !flag) || (flag2 == flag && (num3 > num || (num3 == num && string.CompareOrdinal(((object)Unsafe.As<ZDOID, ZDOID>(ref zDO.m_uid)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<ZDOID, ZDOID>(ref val.m_uid)/*cast due to .constrained prefix*/).ToString()) < 0)))) { val = zDO; num = num3; flag = flag2; } } if (val != null) { val.Set(CanonicalKey, true); foreach (ZDO item in list2) { if (!(item.m_uid == val.m_uid)) { item.Set(CanonicalKey, false); item.Set(ArchivedKey, true); } } } if (num2 > 1 && DuplicateWarnings.Add(playerId)) { plugin.LogBackpackWarning("Found " + num2 + " persistent Rusty Backpack ZDOs for playerId=" + playerId + ". The canonical-backpack recovery path preserves every other saved object and its contents."); } if (val != null && plugin.VerboseLoggingValue) { plugin.LogBackpackInfo(string.Concat("RECOVERED global dedicated backpack zdo=", val.m_uid, " playerId=", playerId, " itemStacks=", num, ".")); } return val; } catch (Exception ex) { globalLookupFailed = true; plugin.LogBackpackWarning("Global backpack recovery failed for playerId=" + playerId + ": " + ex.Message); return null; } } private static ZDO CreateDedicatedBackpackZdo(Vector3 position, long peerId, long playerId, int slots, byte[] inventoryBytes, Plugin plugin) { //IL_005b: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab("piece_chest_private"); if ((Object)(object)prefab == (Object)null) { prefab = ZNetScene.instance.GetPrefab("piece_chest_wood"); } if ((Object)(object)prefab == (Object)null) { plugin.LogBackpackError("Could not find a vanilla chest prefab to host the dedicated Rusty backpack."); return null; } ServerQoLRules.GetBackpackInventorySize(slots, out var width, out var height); int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); ZDO val = ZDOMan.instance.CreateNewZDO(position, stableHashCode); if (val == null) { return null; } val.SetPrefab(stableHashCode); val.SetRotation(Quaternion.identity); val.Persistent = true; ZNetView component = prefab.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { val.SetType(component.m_type); } val.SetDistant(true); val.Set(MarkerKey, true); val.Set(CanonicalKey, true); val.Set(PlayerKey, playerId); val.Set(SlotsKey, slots, false); val.Set(ZDOVars.s_addedDefaultItems, true); SetContainerCustomFields(val, width, height, "Rusty Backpack"); if (inventoryBytes != null && inventoryBytes.Length > 0) { val.Set(ZDOVars.s_items, inventoryBytes); } val.SetOwner(peerId); ZDOMan.instance.ForceSendZDO(peerId, val.m_uid); return val; } private static void SetContainerCustomFields(ZDO zdo, int width, int height, string name) { zdo.Set("HasFields", true); zdo.Set("HasFieldsContainer", true); zdo.Set("Container.m_width", width); zdo.Set("Container.m_height", height); zdo.Set("Container.m_name", name); zdo.Set("Container.m_checkGuardStone", false); zdo.Set("Container.m_autoDestroyEmpty", false); zdo.Set("HasFieldsPiece", true); zdo.Set("Piece.m_canBeRemoved", false); } private static ZDO ResizeDedicatedBackpack(DedicatedPlayerState state, ZDO playerZdo, ZDO oldZdo, int desiredSlots, Plugin plugin) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) int num = Math.Max(1, oldZdo.GetInt("Container.m_width", 8)); int height = Math.Max(oldZdo.GetInt("Container.m_height", 1), (desiredSlots + num - 1) / num); oldZdo.Set(SlotsKey, desiredSlots, false); SetContainerCustomFields(oldZdo, num, height, "Rusty Backpack"); ZDOMan.instance.ForceSendZDO(state.PeerId, oldZdo.m_uid); return oldZdo; } private static void MaintainDedicatedBackpack(DedicatedPlayerState state, ZDO playerZdo, ZNetPeer peer, Plugin plugin) { //IL_0011: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (!EnsureDedicatedBackpack(state, playerZdo, plugin)) { return; } ZDO zDO = ZDOMan.instance.GetZDO(state.BackpackId); if (zDO != null) { zDO.SetDistant(true); Vector3 val = playerZdo.GetPosition() + Vector3.down * 0.6f; Vector3 val2 = zDO.GetPosition() - val; if (((Vector3)(ref val2)).sqrMagnitude > 2.25f) { MoveDedicatedZdo(zDO, val, peer.m_uid); } if (zDO.GetOwner() != peer.m_uid) { zDO.SetOwner(peer.m_uid); } if (Time.realtimeSinceStartup >= state.NextAssigned) { state.NextAssigned = Time.realtimeSinceStartup + 5f; ZDOMan.instance.ForceSendZDO(peer.m_uid, zDO.m_uid); ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "RHSQOL_BackpackAssigned_v2", new object[1] { zDO.m_uid }); } } } private static void MoveDedicatedZdo(ZDO zdo, Vector3 position, long peerId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) zdo.SetPosition(position); ZDOMan.instance.ForceSendZDO(peerId, zdo.m_uid); } private static void OpenDedicatedBackpack(DedicatedPlayerState state, ZDO playerZdo, ZNetPeer peer, Plugin plugin) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!EnsureDedicatedBackpack(state, playerZdo, plugin)) { return; } ZDO zDO = ZDOMan.instance.GetZDO(state.BackpackId); if (zDO != null) { zDO.SetDistant(true); if (zDO.GetOwner() != peer.m_uid) { zDO.SetOwner(peer.m_uid); } MoveDedicatedZdo(zDO, playerZdo.GetPosition() + Vector3.down * 0.6f, peer.m_uid); ZDOMan.instance.ForceSendZDO(peer.m_uid, zDO.m_uid); ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "RHSQOL_BackpackOpen_v1", new object[1] { zDO.m_uid }); if (plugin.VerboseLoggingValue) { plugin.LogBackpackInfo(string.Concat("OPEN-SENT dedicated backpack zdo=", zDO.m_uid, " player=", peer.m_playerName, " attemptsLeft=", state.OpenAttemptsRemaining, ".")); } } } private static void GetStoredInventorySize(ZDO zdo, int slots, out int width, out int height) { ServerQoLRules.GetBackpackInventorySize(slots, out width, out height); width = Math.Max(1, zdo.GetInt("Container.m_width", width)); height = Math.Max(1, zdo.GetInt("Container.m_height", height)); } private static Inventory LoadInventoryFromZdo(ZDO zdo, int width, int height) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Inventory val = new Inventory("Rusty Backpack", (Sprite)null, width, height); byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray != null && byteArray.Length > 0) { ZPackage val2 = new ZPackage(); val2.Load(byteArray); val.Load(val2); } return val; } private static byte[] SaveInventoryBytes(Inventory inventory) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); inventory.Save(val); return val.GetArray(); } private static void HandleDedicatedDeath(DedicatedPlayerState state, ZDO playerZdo, ZNetPeer peer, Plugin plugin) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_00a3: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: 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_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) ZDO val = (((ZDOID)(ref state.BackpackId)).IsNone() ? null : ZDOMan.instance.GetZDO(state.BackpackId)); if (!IsDedicatedBackpackFor(val, state.PlayerId)) { val = FindDedicatedBackpackGlobal(state.PlayerId, plugin); } if (val == null) { return; } if (state.DeathSnapshot == null || state.DeathSnapshotId != val.m_uid) { plugin.LogBackpackWarning("DEATH owner snapshot unavailable for " + peer.m_playerName + "; keeping the original backpack intact rather than destroying a possibly stale inventory."); return; } int slots = Math.Max(1, val.GetInt(SlotsKey, plugin.BackpackInitialSlotsValue)); GetStoredInventorySize(val, slots, out var width, out var height); Inventory val2; if (state.DeathSnapshot != null && state.DeathSnapshotId == val.m_uid) { val2 = new Inventory("Rusty Backpack", (Sprite)null, width, height); ZPackage val3 = new ZPackage(); val3.Load(state.DeathSnapshot); val2.Load(val3); } else { val2 = LoadInventoryFromZdo(val, width, height); } if (val2 == null || val2.NrOfItems() == 0) { if (plugin.VerboseLoggingValue) { plugin.LogBackpackInfo("DEATH backpack empty for " + peer.m_playerName + "; no Rusty Backpack tombstone needed."); } if (val2 != null) { DestroyDedicatedZdo(val); CanonicalBackpacks.Remove(state.PlayerId); state.BackpackId = ZDOID.None; } return; } GameObject prefab = ZNetScene.instance.GetPrefab("Player_tombstone"); if ((Object)(object)prefab == (Object)null) { plugin.LogBackpackError("Player_tombstone prefab missing; keeping Rusty Backpack intact after death."); return; } int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); ZDO grave = ((state.DeathLocation == null || ((ZDOID)(ref state.DeathLocation.GraveId)).IsNone()) ? null : ZDOMan.instance.GetZDO(state.DeathLocation.GraveId)); ZDOID anchor; Vector3 val4 = BackpackDeathPlacement.Resolve(state.DeathLocation, state.DeathPoint, grave, state.PlayerId, out anchor); if (!BackpackDeathPlacement.Finite(val4)) { plugin.LogBackpackError("Death location invalid; original backpack kept intact."); return; } ZDO val5 = ZDOMan.instance.CreateNewZDO(val4, stableHashCode); if (val5 != null) { val5.SetPrefab(stableHashCode); val5.SetRotation(Quaternion.identity); val5.Persistent = true; ZNetView component = prefab.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { val5.SetType(component.m_type); val5.SetDistant(component.m_distant); } val5.Set(ZDOVars.s_addedDefaultItems, true); val5.Set("RHSQOL_RustyBackpack_Grave", true); if (!((ZDOID)(ref anchor)).IsNone()) { val5.Set("RHSQOL_RustyBackpack_DeathAnchor", anchor); } val5.Set(ZDOVars.s_owner, state.PlayerId); val5.Set(ZDOVars.s_ownerName, peer.m_playerName + " - Rusty Backpack"); SetContainerCustomFields(val5, width, height, peer.m_playerName + " - Rusty Backpack"); val5.Set(ZDOVars.s_items, SaveInventoryBytes(val2)); val5.SetOwner(peer.m_uid); ZDOMan.instance.ForceSendZDO(peer.m_uid, val5.m_uid); Inventory val6 = LoadInventoryFromZdo(val5, width, height); if (val6.NrOfItems() != val2.NrOfItems()) { DestroyDedicatedZdo(val5); plugin.LogBackpackError("Death grave verification failed; original backpack kept intact."); return; } DestroyDedicatedZdo(val); CanonicalBackpacks.Remove(state.PlayerId); state.BackpackId = ZDOID.None; state.OpenAt = -1f; plugin.LogBackpackInfo(string.Concat("DEATH dropped Rusty Backpack tombstone for ", peer.m_playerName, " with ", val2.NrOfItems(), " item stack(s). inventoryGrave=", anchor, " position=", val4, ".")); } } private static void RememberDeathPoint(DedicatedPlayerState state, ZDO player) { //IL_000b: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!state.HasDeathPoint) { state.DeathPoint = player.GetPosition() + Vector3.up; state.HasDeathPoint = true; } } private static void DestroyDedicatedZdo(ZDO zdo) { if (zdo != null) { zdo.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(zdo); } } internal static void NotifyDedicatedPlayerDeath(Player player) { //IL_009f: 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) //IL_0127: 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_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) Plugin instance = Plugin.Instance; if (!ActivationAllowed(instance) || (Object)(object)player == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !ZNet.instance.IsDedicated() || ZDOMan.instance == null) { return; } try { ZNetView component = ((Component)player).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component == (Object)null) ? null : component.GetZDO()); if (val == null || !val.IsValid()) { return; } long num = val.GetLong(ZDOVars.s_playerID, 0L); DedicatedPlayerState dedicatedPlayerState = null; foreach (KeyValuePair<long, DedicatedPlayerState> dedicatedState in DedicatedStates) { if (dedicatedState.Value.CharacterId == val.m_uid || (num != 0 && dedicatedState.Value.PlayerId == num)) { dedicatedPlayerState = dedicatedState.Value; break; } } ZNetPeer val2 = null; IList<ZNetPeer> list = new List<ZNetPeer>(ZNet.instance.GetPeers()); for (int i = 0; i < list.Count; i++) { ZNetPeer val3 = list[i]; if (val3 != null && ((dedicatedPlayerState != null && val3.m_uid == dedicatedPlayerState.PeerId) || val3.m_characterID == val.m_uid)) { val2 = val3; break; } } if (dedicatedPlayerState == null && val2 != null && num != 0) { DedicatedPlayerState dedicatedPlayerState2 = new DedicatedPlayerState(); dedicatedPlayerState2.PeerId = val2.m_uid; dedicatedPlayerState2.PlayerId = num; dedicatedPlayerState2.CharacterId = val.m_uid; dedicatedPlayerState2.LastEmoteId = val.GetInt(ZDOVars.s_emoteID, 0); dedicatedPlayerState2.LastDead = true; dedicatedPlayerState = dedicatedPlayerState2; DedicatedStates[val2.m_uid] = dedicatedPlayerState; } if (dedicatedPlayerState == null || val2 == null) { instance.LogBackpackWarning("DEATH RPC detected but no tracked peer/state could be resolved for playerId=" + num + "."); return; } dedicatedPlayerState.LastDead = true; dedicatedPlayerState.DeathConfirmed = true; RememberDeathPoint(dedicatedPlayerState, val); dedicatedPlayerState.OpenAt = -1f; dedicatedPlayerState.OpenAttemptsRemaining = 0; instance.LogBackpackInfo("DEATH RPC detected for " + val2.m_playerName + " playerId=" + dedicatedPlayerState.PlayerId + "."); if (dedicatedPlayerState.PendingDeathAt < 0f) { dedicatedPlayerState.PendingDeathAt = Time.realtimeSinceStartup + 1f; } } catch (Exception ex) { instance.LogBackpackError("Dedicated death RPC handling failed: " + ex); } } internal static void QueueLocalOpen(Player player, string emote, bool emoteStarted) { Plugin instance = Plugin.Instance; if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && ActivationAllowed(instance) && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsDedicated() && ZNet.instance.IsServer()) { string backpackOpenEmoteValue = instance.BackpackOpenEmoteValue; if (string.Equals(emote ?? string.Empty, backpackOpenEmoteValue ?? "wave", StringComparison.OrdinalIgnoreCase)) { openAt = Time.realtimeSinceStartup + 0.15f; } } } private static void OpenBackpackNow(Player player, Plugin plugin) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!EnsureBackpack(player, plugin) || (Object)(object)backpack == (Object)null || (Object)(object)InventoryGui.instance == (Object)null) { return; } FollowPlayer(player); try { backpack.SetInUse(true); InventoryGui.instance.Show(backpack, 1); if (plugin.VerboseLoggingValue) { Inventory inventory = backpack.GetInventory(); plugin.LogBackpackInfo(string.Concat("OPEN local-test backpack zdo=", backpackId, " size=", inventory.GetWidth(), "x", inventory.GetHeight(), " items=", inventory.NrOfItems(), ".")); } } catch (Exception ex) { plugin.LogBackpackError("Open failed: " + ex); } } private static bool EnsureBackpack(Player player, Plugin plugin) { if ((Object)(object)backpackObject != (Object)null && (Object)(object)backpack != (Object)null) { return true; } long playerID = player.GetPlayerID(); GameObject val = FindExistingBackpack(player, playerID, plugin); if ((Object)(object)val != (Object)null) { BindRuntimeBackpack(val); EnsureCapacity(player, plugin); return (Object)(object)backpack != (Object)null; } int desiredSlots = GetDesiredSlots(plugin); GameObject val2 = CreateHiddenBackpack(player, playerID, desiredSlots, plugin); if ((Object)(object)val2 == (Object)null) { return false; } BindRuntimeBackpack(val2); return (Object)(object)backpack != (Object)null; } private static GameObject FindExistingBackpack(Player player, long playerId, Plugin plugin) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be du