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 ServersideQoL Backpack v2.0.14
ServersideQoL.Backpack.dll
Decompiled 12 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using ServersideQoL.Processors; using ServersideQoL.Utilities; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ArgusMagnus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("ArgusMagnus")] [assembly: AssemblyDescription("Adds a backpack with progressively larger storage capacity")] [assembly: AssemblyFileVersion("2.0.14.0")] [assembly: AssemblyInformationalVersion("2.0.14+62f64f08270f57d15cc5ce6dd882c86ea0c0ad0f")] [assembly: AssemblyProduct("ServersideQoL.Backpack")] [assembly: AssemblyTitle("ServersideQoL.Backpack")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ArgusMagnus/ValheimServersideQoL")] [assembly: AssemblyVersion("2.0.14.0")] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Count; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Count; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyList(List<T> items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return _items.Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { _items.CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return _items.IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ServersideQoL.Backpack { [BepInPlugin("ArgusMagnus.ServersideQoL.Backpack", "ServersideQoL.Backpack", "2.0.14")] public sealed class BackpackPlugin : ServersideQoLPluginBase<BackpackPlugin, Config> { public const string Author = "ArgusMagnus"; public const string PluginName = "ServersideQoL.Backpack"; public const string PluginGuid = "ArgusMagnus.ServersideQoL.Backpack"; public const string PluginVersion = "2.0.14"; public const string PluginInformationalVersion = "2.0.14"; private DateTimeOffset BuildTimestamp { get; } = new DateTimeOffset(639255215820543236L, default(TimeSpan)); protected override Config CreateConfigSingleton(ConfigFile configFile, Logger logger) { return new Config(configFile, logger); } protected override void RegisterProcessors(IProcessorCollection processors) { processors.Add<BackpackProcessor>(); } private void Awake() { } } [Processor("fdd88a40-add7-413c-ac4b-894ac26c500d")] [DependsOn<PlayerRegistryProcessor>] [DependsOn<ContainerRegistryProcessor>] internal sealed class BackpackProcessor : Processor<BackpackProcessor.PrefabInfo> { public sealed record PrefabInfo(Container? Container, Player? Player) : ProcessorPrefabInfo() { [MemberNotNullWhen(true, "Container")] public bool IsBackpack { [MemberNotNullWhen(true, "Container")] get; [MemberNotNullWhen(true, "Container")] private set; } [MemberNotNullWhen(true, "Container")] public bool IsBackpackTombstone { [MemberNotNullWhen(true, "Container")] get; [MemberNotNullWhen(true, "Container")] private set; } public override bool IsValid { get { if (Player == null && !(IsBackpack = ((ProcessorPrefabInfo)this).PrefabInfo.PrefabHash == BackpackPrefabHash)) { return IsBackpackTombstone = ((ProcessorPrefabInfo)this).PrefabInfo.PrefabHash == BackpackTombstonePrefab; } return true; } } [CompilerGenerated] public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("PrefabInfo"); stringBuilder.Append(" { "); if (((ProcessorPrefabInfo)this).PrintMembers(stringBuilder)) { stringBuilder.Append(' '); } stringBuilder.Append('}'); return stringBuilder.ToString(); } [CompilerGenerated] protected override bool PrintMembers(StringBuilder builder) { if (((ProcessorPrefabInfo)this).PrintMembers(builder)) { builder.Append(", "); } builder.Append("Container = "); builder.Append(Container); builder.Append(", Player = "); builder.Append(Player); builder.Append(", IsBackpack = "); builder.Append(IsBackpack.ToString()); builder.Append(", IsBackpackTombstone = "); builder.Append(IsBackpackTombstone.ToString()); return true; } [CompilerGenerated] public override int GetHashCode() { return (((((ProcessorPrefabInfo)this).GetHashCode() * -1521134295 + EqualityComparer<Container>.Default.GetHashCode(Container)) * -1521134295 + EqualityComparer<Player>.Default.GetHashCode(Player)) * -1521134295 + EqualityComparer<bool>.Default.GetHashCode(IsBackpack)) * -1521134295 + EqualityComparer<bool>.Default.GetHashCode(IsBackpackTombstone); } [CompilerGenerated] public sealed override bool Equals(ProcessorPrefabInfo? other) { return ((object)this).Equals((object?)other); } [CompilerGenerated] public bool Equals(PrefabInfo? other) { if ((object)this != other) { if (((ProcessorPrefabInfo)this).Equals((ProcessorPrefabInfo)(object)other) && EqualityComparer<Container>.Default.Equals(Container, other.Container) && EqualityComparer<Player>.Default.Equals(Player, other.Player) && EqualityComparer<bool>.Default.Equals(IsBackpack, other.IsBackpack)) { return EqualityComparer<bool>.Default.Equals(IsBackpackTombstone, other.IsBackpackTombstone); } return false; } return true; } [CompilerGenerated] private PrefabInfo(PrefabInfo original) : base((ProcessorPrefabInfo)(object)original) { Container = original.Container; Player = original.Player; IsBackpack = original.IsBackpack; IsBackpackTombstone = original.IsBackpackTombstone; } } private sealed class State(BackpackProcessor processor, PlayerState playerState) { private readonly BackpackProcessor _processor = processor; private ServersideQoLZDO? _backpackContainer; public PlayerState PlayerState { get; } = playerState; public Container? Container { get; private set; } public ServersideQoLZDO? BackpackContainer { get { return _backpackContainer; } set { if (_backpackContainer != null) { processor._backpacks.Remove(_backpackContainer); } _backpackContainer = value; if (_backpackContainer != null) { processor._backpacks.Add(_backpackContainer, this); _backpackContainer.Destroyed += OnBackpackDestroyed; } } } public Timestamp? OpenBackpackAfter { get; set; } private void OnBackpackDestroyed(ServersideQoLZDO backpack) { processor._backpacks.Remove(backpack); if (backpack == _backpackContainer) { _backpackContainer = null; } } [MemberNotNull(new string[] { "BackpackContainer", "Container" })] public bool EnsureBackpackExists() { //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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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_00be: 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) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) int privateChest = Prefabs.PrivateChest; Vector3 position = PlayerState.ZDO.ZDO.GetPosition(); position.y -= 0.6f; if (BackpackContainer == null) { BackpackContainer = GetExistingBackpack(); ServersideQoLZDO? backpackContainer = BackpackContainer; if (backpackContainer != null) { backpackContainer.Fields<Container>().Set((Func<Expression<Func<Container, string>>>)(() => (Container x) => x.m_name), ConfigBase<Config>.Instance.Localization.Value.BackpackName, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 377); } } if (BackpackContainer == null) { BackpackContainer = ((Processor)processor).PlacePiece(position, privateChest, 0f, (CreatorMarkers)2); ZDOVars vars = BackpackContainer.Vars; ((ZDOVars)(ref vars)).SetPlayerID(PlayerState.PlayerID, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 390); BackpackContainer.Fields<Container>().Set((Func<Expression<Func<Container, string>>>)(() => (Container x) => x.m_name), ConfigBase<Config>.Instance.Localization.Value.BackpackName, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 391); AdjustSize(BackpackContainer, processor._backpackSlots); BackpackContainer.ZDO.SetOwnerInternal(PlayerState.Owner); } else { if (!(Vector3.Distance(PlayerState.ZDO.ZDO.GetPosition(), BackpackContainer.ZDO.GetPosition()) > InventoryGui.instance.m_autoCloseDistance) && !AdjustSize(BackpackContainer, processor._backpackSlots)) { Container = Processor.GetPrefabInfo(BackpackContainer).GetRequiredComponent<Container>(); return true; } BackpackContainer.ZDO.SetPosition(position); BackpackContainer.ZDO.SetOwnerInternal(PlayerState.Owner); BackpackContainer = ((Processor)processor).RecreatePiece(BackpackContainer); } Container = Processor.GetPrefabInfo(BackpackContainer).GetRequiredComponent<Container>(); return false; static bool AdjustSize(ServersideQoLZDO zdo, int slots) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) ComponentFieldAccessor<Container> val = zdo.Fields<Container>(); ContainerState state = Processor.Instance<ContainerRegistryProcessor>().GetState(zdo); IInventory inventory = state.GetInventory(); int num = Math.Max(slots, inventory.Items.Count); ValueTuple<int, int> inventorySize = Processor.GetInventorySize(num, true); int item = inventorySize.Item1; int item2 = inventorySize.Item2; bool num2 = val.UpdateValue((Func<Expression<Func<Container, int>>>)(() => (Container x) => x.m_width), item, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 352); bool flag = val.UpdateValue((Func<Expression<Func<Container, int>>>)(() => (Container x) => x.m_height), item2, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 353); if (!num2 && !flag) { return false; } using (List<ItemData>.Enumerator enumerator = inventory.Items.GetEnumerator()) { int num3 = 0; while (true) { if (num3 >= item2) { flag = true; break; } int num4 = 0; while (true) { if (num4 >= item) { num3++; break; } if (!enumerator.MoveNext()) { zdo.ClaimOwnershipInternal(); inventory.Save(); flag = true; goto end_IL_0106; } enumerator.Current.m_gridPos = new Vector2i(num4, num3); num4++; } continue; end_IL_0106: break; } } return flag; } } private ServersideQoLZDO? GetExistingBackpack() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) ServersideQoLZDO val = null; Container val2 = null; CreatorMarkers val3 = default(CreatorMarkers); foreach (ServersideQoLZDO placedObject in ((Processor)processor).PlacedObjects) { PrefabInfo processorPrefabInfo = Processor<PrefabInfo>.GetProcessorPrefabInfo(placedObject); if ((object)processorPrefabInfo == null) { continue; } Container container = processorPrefabInfo.Container; if (container == null || !placedObject.IsModCreator(ref val3) || (int)val3 != 2) { continue; } ZDOVars vars = placedObject.Vars; if (((ZDOVars)(ref vars)).GetPlayerID(default(PlayerID)) != PlayerState.PlayerID) { continue; } if (val == null) { val2 = container; val = placedObject; continue; } IInventory inventory = Processor.Instance<ContainerRegistryProcessor>().GetState(val, val2).GetInventory(); if (inventory.Items.Count == 0) { val.Destroy(); val2 = container; val = placedObject; continue; } IInventory inventory2 = Processor.Instance<ContainerRegistryProcessor>().GetState(placedObject, container).GetInventory(); if (inventory2.Items.Count == 0) { placedObject.Destroy(); continue; } ((Processor)processor).Logger.LogWarning((object)("Additional backpack found for player " + PlayerState.PlayerName + ", dropping backpack tombstone at player location")); processor.CreateBackpackTombstone(PlayerState, PlayerState.Owner, inventory2); placedObject.Destroy(); } return val; } } public const string Id = "fdd88a40-add7-413c-ac4b-894ac26c500d"; private readonly Dictionary<ServersideQoLZDO, State> _backpacks = new Dictionary<ServersideQoLZDO, State>(); private readonly Dictionary<ServersideQoLZDO, State> _backpacksByPlayer = new Dictionary<ServersideQoLZDO, State>(); private int _backpackSlots; private static readonly ServerVar<bool> __isBackpackTombstone = ServersideQoLPluginBaseCore<BackpackPlugin, Config>.RegisterServerVar<bool>("IsBackbackTombstone"); private static int BackpackPrefabHash => Prefabs.PrivateChest; private static int BackpackTombstonePrefab => Prefabs.TombStone; protected override void Initialize() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Invalid comparison between Unknown and I4 _backpacks.Clear(); _backpacksByPlayer.Clear(); Processor.Instance<PlayerRegistryProcessor>().EmoteDetected -= OnEmoteDetected; Processor.Instance<PlayerRegistryProcessor>().EmoteDetected += OnEmoteDetected; Intercept.UpdateInterception(Player.OnDeath, (Delegate)new Action<RoutedRPCData>(RPC_OnDeath), ConfigBase<Config>.Instance.BackpackOnDeath.Value != Config.BackPackOnDeathOptions.Keep); ServersideQoLPluginBaseCore<ServersideQoLPlugin, Config>.Instance.GlobalKeysChanged -= UpdateBackpackSlots; if ((int)ConfigBase<Config>.Instance.OpenBackpackEmote.Value == -1) { _backpackSlots = 0; return; } UpdateBackpackSlots(); if (ConfigBase<Config>.Instance.AdditionalBackpackSlotsPerDefeatedBoss.Value != 0) { ServersideQoLPluginBaseCore<ServersideQoLPlugin, Config>.Instance.GlobalKeysChanged += UpdateBackpackSlots; } } protected override ProcessResult Process(ServersideQoLZDO zdo, IReadOnlyList<Peer> peers, PrefabInfo prefabInfo) { //IL_0034: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_021e: 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_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: 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_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) ProcessResult result; Timestamp now; if (prefabInfo.IsBackpack) { if (!_backpacks.TryGetValue(zdo, out State value)) { result = (ProcessResult)((!((Processor)this).PlacedObjects.Contains(zdo)) ? 2 : 0); } else { result = (ProcessResult)0; bool flag = false; bool flag2 = false; float num = 0f; ContainerState state = Processor.Instance<ContainerRegistryProcessor>().GetState(zdo, prefabInfo.Container); IInventory inventory = state.GetInventory(); Vector3 position = value.PlayerState.ZDO.ZDO.GetPosition(); position.y += 2f; for (int num2 = inventory.Items.Count - 1; num2 >= 0; num2--) { ItemData val = inventory.Items[num2]; bool flag3 = false; if (!Processor.IsItemTeleportable(val)) { flag = true; flag3 = true; } else { num += val.GetWeight(-1); if (ConfigBase<Config>.Instance.MaxBackpackWeight.Value > 0 && num > (float)ConfigBase<Config>.Instance.MaxBackpackWeight.Value) { flag2 = true; flag3 = true; } } if (flag3) { ItemDrop.DropItem(val, 0, position, value.PlayerState.ZDO.ZDO.GetRotation()); inventory.Items.RemoveAt(num2); } } if (flag || flag2) { long owner = zdo.ZDO.GetOwner(); zdo.ClaimOwnershipInternal(); inventory.Save(); zdo.ZDO.SetOwnerInternal(owner); value.BackpackContainer = ((Processor)this).RecreatePiece(zdo); RPC.ShowMessage(owner, (MessageType)2, flag ? ConfigBase<Config>.Instance.Localization.Value.ForbiddenItems : ConfigBase<Config>.Instance.Localization.Value.FormatWeightLimitExceeded(ConfigBase<Config>.Instance.MaxBackpackWeight.Value)); State state2 = value; now = Timestamp.Now; state2.OpenBackpackAfter = ((Timestamp)(ref now)).AddSeconds(ConfigBase<Config>.Instance.Advanced.Value.OpenBackpackDelay); } } } else if (prefabInfo.IsBackpackTombstone) { if (!__isBackpackTombstone.Get(zdo, false)) { result = (ProcessResult)2; } else { PlayerRegistryProcessor obj = Processor.Instance<PlayerRegistryProcessor>(); ZDOVars vars = zdo.Vars; PlayerState stateForPlayerID = obj.GetStateForPlayerID(((ZDOVars)(ref vars)).GetCreator(default(PlayerID))); if (stateForPlayerID != null) { vars = stateForPlayerID.ZDO.Vars; if (!((ZDOVars)(ref vars)).GetIsDead(false) && Vector3.Distance(stateForPlayerID.ZDO.ZDO.GetPosition(), zdo.ZDO.GetPosition()) < ConfigBase<Config>.Instance.Advanced.Value.BackpackOnDeathDropTombStone.AutoCollectDistance && _backpacksByPlayer.TryGetValue(stateForPlayerID.ZDO, out State value2)) { value2.EnsureBackpackExists(); IInventory inventory2 = Processor.Instance<ContainerRegistryProcessor>().GetState(zdo, prefabInfo.Container).GetInventory(); IInventory inventory3 = Processor.Instance<ContainerRegistryProcessor>().GetState(value2.BackpackContainer, value2.Container).GetInventory(); foreach (ItemData item in inventory2.Items) { if (!inventory3.Inventory.AddItem(item)) { DropBackpackItem(item, zdo, stateForPlayerID.Owner); } } value2.BackpackContainer.ClaimOwnershipInternal(); inventory3.Save(); RPC.ShowMessage(stateForPlayerID.Owner, (MessageType)2, "$piece_tombstone_recovered (" + ConfigBase<Config>.Instance.Localization.Value.BackpackName + ")"); zdo.Destroy(); } } result = ((Processor)this).ScheduleReprocessing(0.1f); } } else if (prefabInfo.Player != null) { if (_backpacksByPlayer.TryGetValue(zdo, out State value3) && value3.BackpackContainer != null) { Timestamp? openBackpackAfter = value3.OpenBackpackAfter; now = Timestamp.Now; if (openBackpackAfter.HasValue && openBackpackAfter.GetValueOrDefault() < now) { value3.OpenBackpackAfter = null; ZDORpc rPC = value3.BackpackContainer.RPC; ContainerRpc container = ((ZDORpc)(ref rPC)).Container; ((ContainerRpc)(ref container)).OpenResponse(true); } else if (value3.BackpackContainer.ZDO.GetPosition().y > -1000f && Vector3.Distance(zdo.ZDO.GetPosition(), value3.BackpackContainer.ZDO.GetPosition()) > InventoryGui.instance.m_autoCloseDistance) { ZDO zDO = value3.BackpackContainer.ZDO; Vector3 position2 = value3.BackpackContainer.ZDO.GetPosition(); position2.y = -1000f; zDO.SetPosition(position2); value3.BackpackContainer = ((Processor)this).RecreatePiece(value3.BackpackContainer); } } result = ((Processor)this).ScheduleReprocessing(0.1f); } else { result = (ProcessResult)2; } return result; } private void UpdateBackpackSlots() { _backpackSlots = ConfigBase<Config>.Instance.InitialBackpackSlots.Value; if (ConfigBase<Config>.Instance.AdditionalBackpackSlotsPerDefeatedBoss.Value != 0) { _backpackSlots += ConfigBase<Config>.Instance.AdditionalBackpackSlotsPerDefeatedBoss.Value * Processor.BossesByBiome.Values.Count((Character x) => ZoneSystem.instance.GetGlobalKey(x.m_defeatSetGlobalKey)); } } private State GetState(PlayerState playerState) { if (!_backpacksByPlayer.TryGetValue(playerState.ZDO, out State value)) { _backpacksByPlayer.Add(playerState.ZDO, value = new State(this, playerState)); playerState.ZDO.Destroyed += delegate(ServersideQoLZDO zdo) { if (_backpacksByPlayer.Remove(zdo, out State value2)) { value2.BackpackContainer = null; } }; } return value; } private void OnEmoteDetected(PlayerState playerState, Emotes emote) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0053: Unknown result type (might be due to invalid IL or missing references) if ((int)ConfigBase<Config>.Instance.OpenBackpackEmote.Value == -2 || ConfigBase<Config>.Instance.OpenBackpackEmote.Value == emote) { State state = GetState(playerState); if (!state.EnsureBackpackExists()) { Timestamp now = Timestamp.Now; state.OpenBackpackAfter = ((Timestamp)(ref now)).AddSeconds(ConfigBase<Config>.Instance.Advanced.Value.OpenBackpackDelay); return; } state.OpenBackpackAfter = null; ZDORpc rPC = state.BackpackContainer.RPC; ContainerRpc container = ((ZDORpc)(ref rPC)).Container; ((ContainerRpc)(ref container)).OpenResponse(true); } } private void DestroyBackpack(long peerID) { PlayerState stateForPeerID = Processor.Instance<PlayerRegistryProcessor>().GetStateForPeerID(peerID); if (stateForPeerID != null) { ServersideQoLZDO backpackContainer = GetState(stateForPeerID).BackpackContainer; if (backpackContainer != null) { ((Processor)this).DestroyObject(backpackContainer); ((Processor)this).Logger.LogInfo((object)("Backpack of player '" + stateForPeerID.PlayerName + "' destroyed on death")); } } } private void DropBackpackItem(ItemData item, ServersideQoLZDO refPosZdo, long peerID) { //IL_001b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_006e: Unknown result type (might be due to invalid IL or missing references) Config.AdvancedConfig.BackpackOnDeathDropItemsConfig backpackOnDeathDropItems = ConfigBase<Config>.Instance.Advanced.Value.BackpackOnDeathDropItems; Vector3 position = refPosZdo.ZDO.GetPosition(); Vector2 val = Random.insideUnitCircle * backpackOnDeathDropItems.ScatterRadius; position.x += val.x; position.y += backpackOnDeathDropItems.VerticalOffset; position.z += val.y; ServersideQoLZDO serversideQoLZDO = ((Component)ItemDrop.DropItem(item, 0, position, refPosZdo.ZDO.GetRotation())).GetComponent<ZNetView>().GetZDO().ServersideQoLZDO; serversideQoLZDO.Fields<ItemDrop>().Set((Func<Expression<Func<ItemDrop, bool>>>)(() => (ItemDrop x) => x.m_autoDestroy), !backpackOnDeathDropItems.PreventAutoDestroy, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 228).Set((Func<Expression<Func<ItemDrop, bool>>>)(() => (ItemDrop x) => x.m_autoPickup), !backpackOnDeathDropItems.PreventAutoPickup, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 229); serversideQoLZDO.ZDO.SetOwnerInternal(peerID); } private void DropBackpackItems(long peerID) { PlayerState stateForPeerID = Processor.Instance<PlayerRegistryProcessor>().GetStateForPeerID(peerID); if (stateForPeerID == null) { return; } State state = GetState(stateForPeerID); if (state == null) { return; } ServersideQoLZDO backpackContainer = state.BackpackContainer; if (backpackContainer == null) { return; } Container container = state.Container; if (container == null) { return; } IInventory inventory = Processor.Instance<ContainerRegistryProcessor>().GetState(backpackContainer, container).GetInventory(); foreach (ItemData item in inventory.Items) { DropBackpackItem(item, stateForPeerID.ZDO, peerID); } ((Processor)this).DestroyObject(backpackContainer); ((Processor)this).Logger.LogInfo((object)("Backpack items of player '" + stateForPeerID.PlayerName + "' dropped at death location.")); } private void CreateBackpackTombstone(PlayerState playerState, long peerID, IInventory backpackInventory) { //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_003a: 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_005f: 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_0068: 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_0082: Unknown result type (might be due to invalid IL or missing references) Vector3 position = playerState.ZDO.ZDO.GetPosition(); position.y += ConfigBase<Config>.Instance.Advanced.Value.BackpackOnDeathDropTombStone.VerticalOffset; ServersideQoLZDO val = Processor.Spawn(BackpackTombstonePrefab, position, playerState.ZDO.ZDO.GetRotation(), peerID); __isBackpackTombstone.Set(val, true); ZDOVars vars = val.Vars; ((ZDOVars)(ref vars)).SetOwner(playerState.PlayerID, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 253); vars = val.Vars; ((ZDOVars)(ref vars)).SetOwnerName(playerState.PlayerName + " - " + ConfigBase<Config>.Instance.Localization.Value.BackpackName, "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 254); val.Fields<Container>().Set((Func<Expression<Func<Container, int>>>)(() => (Container x) => x.m_width), backpackInventory.Inventory.GetWidth(), "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 257).Set((Func<Expression<Func<Container, int>>>)(() => (Container x) => x.m_height), backpackInventory.Inventory.GetHeight(), "C:\\repos\\Valheim.ServersideQoL\\ServersideQoL.Backpack\\BackpackProcessor.cs", 258); IInventory inventory = Processor.Instance<ContainerRegistryProcessor>().GetState(val).GetInventory(); foreach (ItemData item in backpackInventory.Items) { inventory.Items.Add(item); } inventory.Save(); } private void DropBackback(long peerID) { PlayerState stateForPeerID = Processor.Instance<PlayerRegistryProcessor>().GetStateForPeerID(peerID); if (stateForPeerID == null) { return; } State state = GetState(stateForPeerID); if (state == null) { return; } ServersideQoLZDO backpackContainer = state.BackpackContainer; if (backpackContainer == null) { return; } Container container = state.Container; if (container != null) { IInventory inventory = Processor.Instance<ContainerRegistryProcessor>().GetState(backpackContainer, container).GetInventory(); if (inventory.Items.Count != 0) { CreateBackpackTombstone(stateForPeerID, peerID, inventory); ((Processor)this).DestroyObject(backpackContainer); ((Processor)this).Logger.LogInfo((object)("Backpack of player '" + stateForPeerID.PlayerName + "' dropped at death location.")); } } } private void RPC_OnDeath(RoutedRPCData data) { switch (ConfigBase<Config>.Instance.BackpackOnDeath.Value) { case Config.BackPackOnDeathOptions.SameAsInventory: if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)20) || ZoneSystem.instance.GetGlobalKey((GlobalKeys)21)) { DestroyBackpack(data.m_senderPeerID); } else if (!ZoneSystem.instance.GetGlobalKey((GlobalKeys)23)) { DropBackback(data.m_senderPeerID); } break; case Config.BackPackOnDeathOptions.Destroy: DestroyBackpack(data.m_senderPeerID); break; case Config.BackPackOnDeathOptions.DropTombStone: DropBackback(data.m_senderPeerID); break; case Config.BackPackOnDeathOptions.DropItems: DropBackpackItems(data.m_senderPeerID); break; case Config.BackPackOnDeathOptions.Keep: break; } } } public sealed class Config : ConfigBase<Config> { public enum BackPackOnDeathOptions { SameAsInventory, Keep, Destroy, DropTombStone, DropItems } public sealed class LocalizationConfig { public string BackpackName { get; init; } = "Backpack"; public string ForbiddenItems { get; init; } = "Backpack cannot contain non-teleportable items"; private string WeightLimitExceeded { get; init; } = "Backpack weight limit ({0}) exceeded"; public string FormatWeightLimitExceeded(int maxWeight) { return string.Format(WeightLimitExceeded, maxWeight); } } public sealed class AdvancedConfig { public sealed record BackpackOnDeathDropTombStoneConfig(float VerticalOffset, float AutoCollectDistance) { private BackpackOnDeathDropTombStoneConfig() : this(0f, 0f) { } } public sealed record BackpackOnDeathDropItemsConfig(float ScatterRadius, float VerticalOffset, bool PreventAutoDestroy, bool PreventAutoPickup) { private BackpackOnDeathDropItemsConfig() : this(0f, 0f, PreventAutoDestroy: false, PreventAutoPickup: false) { } } public float OpenBackpackDelay { get; init; } = 0.2f; public BackpackOnDeathDropTombStoneConfig BackpackOnDeathDropTombStone { get; init; } = new BackpackOnDeathDropTombStoneConfig(2f, 2f); public BackpackOnDeathDropItemsConfig BackpackOnDeathDropItems { get; init; } = new BackpackOnDeathDropItemsConfig(2f, 1f, PreventAutoDestroy: true, PreventAutoPickup: false); } public override ConfigEntry<bool> Enabled { get; } = ConfigBase<Config>.BindEx<bool>(cfg, true, "Enables/disables the entire mod", (AcceptableValueBase)null, (Deprecated<Config>)null, "Enabled"); public ConfigEntry<Emotes> OpenBackpackEmote { get; } public ConfigEntry<int> InitialBackpackSlots { get; } public ConfigEntry<int> AdditionalBackpackSlotsPerDefeatedBoss { get; } public ConfigEntry<int> MaxBackpackWeight { get; } public ConfigEntry<BackPackOnDeathOptions> BackpackOnDeath { get; } public YamlConfigEntry<LocalizationConfig> Localization { get; } public YamlConfigEntry<AdvancedConfig> Advanced { get; } public Config(ConfigFile cfg, Logger logger) { string text = $"Emote to open the backpack.\r\nIf a player uses this emote, a virtual container acting as their backpack will open.\r\n{(object)(Emotes)(-2)} to use any emote as trigger.\r\nYou can bind emotes to buttons with chat commands.\r\nFor example, on xbox you can bind the Y-Button to the wave-emote by entering \"/bind JoystickButton3 {(object)(Emotes)0}\" in the in-game chat.\r\nIf you use emotes exclusively for this feature, it is recommended to set the value to {(object)(Emotes)(-2)} as it is more reliably detected than specific emotes, especially on bad connection/with crossplay."; List<Emotes> list = new List<Emotes>(); list.Add((Emotes)(-2)); list.AddRange(Enum.GetValues(typeof(Emotes)).Cast<Emotes>()); OpenBackpackEmote = ConfigBase<Config>.BindEx<Emotes>(cfg, (Emotes)0, text, (AcceptableValueBase)(object)new AcceptableEnum<Emotes>((IEnumerable<Emotes>)new <>z__ReadOnlyList<Emotes>(list)), (Deprecated<Config>)null, "OpenBackpackEmote"); InitialBackpackSlots = ConfigBase<Config>.BindEx<int>(cfg, 4, "Initial available slots in the backpack", (AcceptableValueBase)null, (Deprecated<Config>)null, "InitialBackpackSlots"); AdditionalBackpackSlotsPerDefeatedBoss = ConfigBase<Config>.BindEx<int>(cfg, 4, "Additional backpack slots per defeated boss", (AcceptableValueBase)null, (Deprecated<Config>)null, "AdditionalBackpackSlotsPerDefeatedBoss"); MaxBackpackWeight = ConfigBase<Config>.BindEx<int>(cfg, 0, "Maximum backpack weight. 0 for no limit.", (AcceptableValueBase)null, (Deprecated<Config>)null, "MaxBackpackWeight"); BackpackOnDeath = ConfigBase<Config>.BindEx<BackPackOnDeathOptions>(cfg, BackPackOnDeathOptions.SameAsInventory, "What happens to backpack contents on player death", (AcceptableValueBase)null, (Deprecated<Config>)null, "BackpackOnDeath"); Localization = ConfigBase<Config>.BindYaml<LocalizationConfig>(cfg, "Localization"); Advanced = ConfigBase<Config>.BindYaml<AdvancedConfig>(cfg, "Advanced"); base..ctor(cfg, logger); } } }