Иконка ресурса

FREE Backpacks : 3.17.8 3.17.8

Нет прав для скачивания
C#:
// #define DEBUG_DROP_ON_DEATH
// #define DEBUG_POOLING
// #define DEBUG_BACKPACK_LIFECYCLE

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Facepunch;
using Network;
using Newtonsoft.Json.Converters;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Rust;
using UnityEngine;
using UnityEngine.UI;
using Time = UnityEngine.Time;

namespace Oxide.Plugins
{
    [Info("Backpacks", "WhiteThunder", "3.17.8")]
    [Description("Allows players to have a Backpack which provides them extra inventory space.")]
    public class Backpacks : CovalencePlugin
    {
        #region Fields

        private static int _maxCapacityPerPage = 48;

        private const int MinRows = 1;
        private const int MaxRows = 8;
        private const int MinContainerCapacity = 1;
        private const int MaxContainerCapacity = 48;
        private const int SlotsPerRow = 6;
        private const float StandardLootDelay = 0.1f;
        private const Item.Flag SearchableItemFlag = (Item.Flag)(1 << 24);
        private const Item.Flag UnsearchableItemFlag = (Item.Flag)(1 << 25);
        private const ItemDefinition.Flag SearchableItemDefinitionFlag = (ItemDefinition.Flag)(1 << 24);

        private const string AdminPermission = "backpacks.admin";
        private const string AdminViewPermission = "backpacks.admin.view";
        private const string AdminEditPermission = "backpacks.admin.edit";
        private const string AdminResizePermission = "backpacks.admin.resize";
        private const string AdminDebugPermission = "backpacks.admin.debug";
        private const string AdminProtectedPermission = "backpacks.admin.protected";

        private const string UsagePermission = "backpacks.use";
        private const string SizePermission = "backpacks.size";
        private const string GUIPermission = "backpacks.gui";
        private const string FetchPermission = "backpacks.fetch";
        private const string GatherPermission = "backpacks.gather";
        private const string RetrievePermission = "backpacks.retrieve";
        private const string CapacityProfilePermission = "backpacks.size.profile";
        private const string KeepOnDeathPermission = "backpacks.keepondeath";
        private const string NoFoodSpoilingPermission = "backpacks.nofoodspoiling";
        private const string LegacyKeepOnWipePermission = "backpacks.keeponwipe";
        private const string LegacyNoBlacklistPermission = "backpacks.noblacklist";

        private const string CoffinPrefab = "assets/prefabs/misc/halloween/coffin/coffinstorage.prefab";
        private const string DroppedBackpackPrefab = "assets/prefabs/misc/item drop/item_drop_backpack.prefab";
        private const string ResizableLootPanelName = "generic_resizable";

        private const int SaddleBagItemId = 1400460850;
        private const float BackpackContainerHeight = -500f;

        private readonly object False = false;

        private readonly CapacityManager _capacityManager;
        private readonly BackpackManager _backpackManager;
        private readonly SubscriberManager _subscriberManager = new();

        private ProtectionProperties _immortalProtection;
        private Effect _reusableEffect = new();
        private string _cachedButtonUi;
        private Vector3 _backpackContainerPosition;

        public readonly ApiInstance Api;
        private Configuration _config;
        private PreferencesData _preferencesData;
        private CapacityData _capacityData;
        private readonly HashSet<ulong> _uiViewers = new();
        private readonly DynamicHookSubscriber<BasePlayer> _readonlyBackpackViewers;
        private Coroutine _saveRoutine;

        [PluginReference]
        private readonly Plugin Arena, BackpackButton, EventManager, ItemRetriever;

        public Backpacks()
        {
            _backpackManager = new BackpackManager(this);
            _capacityManager = new CapacityManager(this, _backpackManager);
            _readonlyBackpackViewers = new DynamicHookSubscriber<BasePlayer>(this, nameof(CanMoveItem), nameof(OnItemAction));
            Api = new ApiInstance(this);
        }

        #endregion

        #region Hooks

        private void Init()
        {
            permission.RegisterPermission(AdminPermission, this);
            permission.RegisterPermission(AdminViewPermission, this);
            permission.RegisterPermission(AdminEditPermission, this);
            permission.RegisterPermission(AdminResizePermission, this);
            permission.RegisterPermission(AdminDebugPermission, this);
            permission.RegisterPermission(AdminProtectedPermission, this);

            permission.RegisterPermission(UsagePermission, this);
            permission.RegisterPermission(GUIPermission, this);
            permission.RegisterPermission(FetchPermission, this);
            permission.RegisterPermission(GatherPermission, this);
            permission.RegisterPermission(RetrievePermission, this);
            permission.RegisterPermission(KeepOnDeathPermission, this);
            permission.RegisterPermission(NoFoodSpoilingPermission, this);

            _config.Init(this);

            _maxCapacityPerPage = Mathf.Clamp(_config.BackpackSize.MaxCapacityPerPage, MinContainerCapacity, MaxContainerCapacity);

            PoolUtils.ResizePools();

            _preferencesData = PreferencesData.Load();
            _capacityData = CapacityData.Exists() ? CapacityData.Load() : new CapacityData();
            _capacityManager.Init(_config, _capacityData);

            Unsubscribe(nameof(OnPlayerSleep));
            Unsubscribe(nameof(OnPlayerSleepEnded));

            _readonlyBackpackViewers.UnsubscribeAll();

            if (_config.GUI.Enabled)
            {
                AddCovalenceCommand("backpackgui", nameof(ToggleBackpackGUICommand));
            }
            else
            {
                Unsubscribe(nameof(OnPlayerConnected));
                Unsubscribe(nameof(OnNpcConversationStart));
                Unsubscribe(nameof(OnNpcConversationEnded));
            }
        }

        private void OnServerInitialized()
        {
            if (TryFindBackpackContainerPositionNotInArcticBiome(out var position, out var sampleCount))
            {
                _backpackContainerPosition = position;
            }
            else
            {
                LogWarning($"Warning: All backpacks will be exempt from food spoiling because the plugin failed to locate a map position outside of the Arctic Biome out of [{sampleCount}] samples.");
                _backpackContainerPosition = new Vector3(0f, BackpackContainerHeight, 0f);
            }

            _immortalProtection = ScriptableObject.CreateInstance<ProtectionProperties>();
            _immortalProtection.name = "BackpacksProtection";
            _immortalProtection.Add(1);

            CheckBackpackButtonPlugin();
            RegisterAsItemSupplier();

            if (_config.GUI.Enabled)
            {
                Subscribe(nameof(OnPlayerSleep));
                Subscribe(nameof(OnPlayerSleepEnded));
                Subscribe(nameof(OnPlayerConnected));
                Subscribe(nameof(OnNpcConversationStart));
                Subscribe(nameof(OnNpcConversationEnded));

                foreach (var player in BasePlayer.activePlayerList)
                {
                    MaybeCreateButtonUi(player);
                }
            }
        }

        private void Unload()
        {
            UnityEngine.Object.Destroy(_immortalProtection);

            RestartSaveRoutine(async: false, keepInUseBackpacks: false);

            BackpackNetworkController.ResetNetworkGroupId();

            foreach (var player in BasePlayer.activePlayerList)
            {
                DestroyButtonUi(player);
            }

            PoolUtils.ResizePools(empty: true);
        }

        private void OnNewSave(string filename)
        {
            PerformBackpackWipe("New save created");
        }

        private void OnServerSave()
        {
            RestartSaveRoutine(async: true, keepInUseBackpacks: true);
        }

        private void OnPluginLoaded(Plugin plugin)
        {
            switch (plugin.Name)
            {
                case nameof(BackpackButton):
                    CheckBackpackButtonPlugin();
                    break;
                case nameof(ItemRetriever):
                    RegisterAsItemSupplier();
                    break;
            }
        }

        private void OnPluginUnloaded(Plugin plugin)
        {
            _subscriberManager.RemoveSubscriber(plugin);
        }

        private void OnPlayerDisconnected(BasePlayer player)
        {
            _capacityManager.ForgetCachedCapacity(player.userID);
            _backpackManager.GetBackpackIfCached(player.userID)?.NetworkController?.Unsubscribe(player);
        }

        // Handle player death by normal means.
        private void OnEntityDeath(BasePlayer player, HitInfo info) =>
            OnEntityKill(player);

        // Handle player death while sleeping in a safe zone.
        private void OnEntityKill(BasePlayer player)
        {
            if (player.IsNpc)
                return;

            DestroyButtonUi(player);

            if (!_backpackManager.HasBackpack(player.userID))
                return;

            if (permission.UserHasPermission(player.UserIDString, KeepOnDeathPermission))
            {
                #if DEBUG_DROP_ON_DEATH
                LogWarning($"[DEBUG_DROP_ON_DEATH] [Player {player.UserIDString}] Backpack not dropped because the player has the {KeepOnDeathPermission} permission.");
                #endif
                return;
            }

            if (_config.EraseOnDeath)
            {
                _backpackManager.TryEraseForPlayer(player.userID);
            }
            else if (_config.DropOnDeath)
            {
                _backpackManager.Drop(player.userID, player.transform.position);
            }
            else
            {
                #if DEBUG_DROP_ON_DEATH
                LogWarning($"[DEBUG_DROP_ON_DEATH] [Player {player.UserIDString}] Backpack not dropped because \"Drop on Death (true/false)\" is set to false in the config.");
                #endif
            }
        }

        private object CanMoveItem(Item item, PlayerInventory playerInventory, ItemContainerId targetContainerId, int targetSlot, int amount)
        {
            var player = playerInventory.baseEntity;
            if (player is null)
                return null;

            if (!IsLootingBackpackOrChildContainer(player, out var backpack, out _)
                || player.userID == backpack.OwnerId)
                return null;

            var itemRootContainer = GetRootContainer(item);
            if (itemRootContainer == null)
                return null;

            var requiresPermission = false;

            if (_backpackManager.IsBackpack(itemRootContainer))
            {
                // The item being moved is inside a backpack or one of its child containers.
                requiresPermission = true;
            }
            else if (!targetContainerId.IsValid)
            {
                // The item is being moved to the backpack or one of its child containers (container not specified).
                requiresPermission = true;
            }
            else
            {
                // The item is being moved to the backpack or one of its child containers (container specified).
                var targetRootContainer = GetRootContainer(playerInventory.FindContainer(targetContainerId));
                if (targetRootContainer != null && _backpackManager.IsBackpack(targetRootContainer))
                {
                    requiresPermission = true;
                }
            }

            if (!requiresPermission || VerifyHasPermissionToEditBackpack(player))
                return null;

            return False;
        }

        private object OnItemAction(Item item, string action, BasePlayer player)
        {
            if (!IsLootingBackpackOrChildContainer(player, out var backpack, out _)
                || player.userID == backpack.OwnerId)
                return null;

            var itemRootContainer = GetRootContainer(item);
            if (itemRootContainer == null
                || !_backpackManager.IsBackpack(itemRootContainer)
                || VerifyHasPermissionToEditBackpack(player))
                return null;

            return False;
        }

        private void OnGroupPermissionGranted(string groupName, string perm)
        {
            if (!perm.StartsWith("backpacks"))
                return;

            if (perm.StartsWith(SizePermission) || perm.StartsWith(UsagePermission) || perm.StartsWith(CapacityProfilePermission))
            {
                _backpackManager.HandleCapacityPermissionChangedForGroup(groupName);
            }
            else if (perm.StartsWith(RestrictionRuleset.FullPermissionPrefix) || perm.Equals(LegacyNoBlacklistPermission))
            {
                _backpackManager.HandleRestrictionPermissionChangedForGroup(groupName);
            }
            else if (perm.Equals(GatherPermission))
            {
                _backpackManager.HandleGatherPermissionChangedForGroup(groupName);
            }
            else if (perm.Equals(RetrievePermission))
            {
                _backpackManager.HandleRetrievePermissionChangedForGroup(groupName);
            }
            else if (perm.Equals(NoFoodSpoilingPermission))
            {
                _backpackManager.HandleFoodSpoilingPermissionChangedForGroup(groupName);
            }
            else if (_config.GUI.Enabled && perm.Equals(GUIPermission))
            {
                var groupName2 = groupName;
                foreach (var player in BasePlayer.activePlayerList.Where(p => permission.UserHasGroup(p.UserIDString, groupName2)))
                {
                    CreateOrDestroyButtonUi(player);
                }
            }
        }

        private void OnGroupPermissionRevoked(string groupName, string perm)
        {
            OnGroupPermissionGranted(groupName, perm);
        }

        private void OnUserPermissionGranted(string userId, string perm)
        {
            if (!perm.StartsWith("backpacks"))
                return;

            if (perm.StartsWith(SizePermission) || perm.StartsWith(UsagePermission) || perm.StartsWith(CapacityProfilePermission))
            {
                _backpackManager.HandleCapacityPermissionChangedForUser(userId);
            }
            else if (perm.StartsWith(RestrictionRuleset.FullPermissionPrefix) || perm.Equals(LegacyNoBlacklistPermission))
            {
                _backpackManager.HandleRestrictionPermissionChangedForUser(userId);
            }
            else if (perm.Equals(GatherPermission))
            {
                _backpackManager.HandleGatherPermissionChangedForUser(userId);
            }
            else if (perm.Equals(RetrievePermission))
            {
                _backpackManager.HandleRetrievePermissionChangedForUser(userId);
            }
            else if (perm.Equals(NoFoodSpoilingPermission))
            {
                _backpackManager.HandleFoodSpoilingPermissionChangedForUser(userId);
            }
            else if (_config.GUI.Enabled && perm.Equals(GUIPermission))
            {
                var player = BasePlayer.Find(userId);
                if (player != null)
                {
                    CreateOrDestroyButtonUi(player);
                }
            }
        }

        private void OnUserPermissionRevoked(string userId, string perm)
        {
            OnUserPermissionGranted(userId, perm);
        }

        private void OnUserGroupAdded(string userId, string groupName)
        {
            _backpackManager.HandleGroupChangeForUser(userId);
        }

        private void OnUserGroupRemoved(string userId, string groupName)
        {
            _backpackManager.HandleGroupChangeForUser(userId);
        }

        // Only subscribed while the GUI button is enabled.
        private void OnPlayerConnected(BasePlayer player) => MaybeCreateButtonUi(player);

        private void OnPlayerRespawned(BasePlayer player)
        {
            // People reported NRE on Carbon framework, meaning the player is somehow null, unknown root cause.
            if (player == null)
                return;

            MaybeCreateButtonUi(player);
            _backpackManager.GetBackpackIfCached(player.userID)?.PauseGatherMode(1f);
        }

        // Only subscribed while the GUI button is enabled.
        private void OnPlayerSleepEnded(BasePlayer player) => OnPlayerRespawned(player);

        // Only subscribed while the GUI button is enabled.
        private void OnPlayerSleep(BasePlayer player) => DestroyButtonUi(player);

        // Only subscribed while the GUI button is enabled.
        private void OnNpcConversationStart(NPCTalking npcTalking, BasePlayer player, ConversationData conversationData)
        {
            // This delay can be removed in the future if an OnNpcConversationStarted hook is created.
            NextTick(() =>
            {
                // Verify the conversation started, since another plugin may have blocked it.
                if (!npcTalking.conversingPlayers.Contains(player))
                    return;

                DestroyButtonUi(player);
            });
        }

        // Only subscribed while the GUI button is enabled.
        private void OnNpcConversationEnded(NPCTalking npcTalking, BasePlayer player) => MaybeCreateButtonUi(player);

        private void OnNetworkSubscriptionsUpdate(Networkable networkable, List<Network.Visibility.Group> groupsToAdd, List<Network.Visibility.Group> groupsToRemove)
        {
            if (groupsToRemove == null)
                return;

            for (var i = groupsToRemove.Count - 1; i >= 0; i--)
            {
                var group = groupsToRemove[i];
                if (BackpackNetworkController.IsBackpackNetworkGroup(group))
                {
                    // Prevent automatically unsubscribing from backpack network groups.
                    // This allows the subscriptions to persist while players move around.
                    groupsToRemove.Remove(group);
                }
            }
        }

        #endregion

        #region API

        public class ApiInstance
        {
            public readonly Dictionary<string, object> ApiWrapper;

            private readonly Backpacks _plugin;
            private BackpackManager _backpackManager => _plugin._backpackManager;

            public ApiInstance(Backpacks plugin)
            {
                _plugin = plugin;

                ApiWrapper = new Dictionary<string, object>
                {
                    [nameof(AddSubscriber)] = new Action<Plugin, Dictionary<string, object>>(AddSubscriber),
                    [nameof(RemoveSubscriber)] = new Action<Plugin>(RemoveSubscriber),
                    [nameof(GetExistingBackpacks)] = new Func<Dictionary<ulong, ItemContainer>>(GetExistingBackpacks),
                    [nameof(EraseBackpack)] = new Action<ulong>(EraseBackpack),
                    [nameof(DropBackpack)] = new Func<BasePlayer, List<DroppedItemContainer>, DroppedItemContainer>(DropBackpack),
                    [nameof(GetBackpackOwnerId)] = new Func<ItemContainer, ulong>(GetBackpackOwnerId),
                    [nameof(IsBackpackLoaded)] = new Func<BasePlayer, bool>(IsBackpackLoaded),
                    [nameof(IsDynamicCapacityEnabled)] = new Func<bool>(IsDynamicCapacityEnabled),
                    [nameof(GetBackpackCapacity)] = new Func<BasePlayer, int>(GetBackpackCapacity),
                    [nameof(GetBackpackCapacityById)] = new Func<ulong, string, int>(GetBackpackCapacityById),
                    [nameof(GetBackpackInitialCapacity)] = new Func<BasePlayer, int>(GetBackpackInitialCapacity),
                    [nameof(GetBackpackMaxCapacity)] = new Func<BasePlayer, int>(GetBackpackMaxCapacity),
                    [nameof(AddBackpackCapacity)] = new Func<BasePlayer, int, int>(AddBackpackCapacity),
                    [nameof(SetBackpackCapacity)] = new Func<BasePlayer, int, int>(SetBackpackCapacity),
                    [nameof(IsBackpackGathering)] = new Func<BasePlayer, bool>(IsBackpackGathering),
                    [nameof(IsBackpackRetrieving)] = new Func<BasePlayer, bool>(IsBackpackRetrieving),
                    [nameof(GetBackpackContainer)] = new Func<ulong, ItemContainer>(GetBackpackContainer),
                    [nameof(GetBackpackItemAmount)] = new Func<ulong, int, ulong, int>(GetBackpackItemAmount),
                    [nameof(TryOpenBackpack)] = new Func<BasePlayer, ulong, bool>(TryOpenBackpack),
                    [nameof(TryOpenBackpackContainer)] = new Func<BasePlayer, ulong, ItemContainer, bool>(TryOpenBackpackContainer),
                    [nameof(TryOpenBackpackPage)] = new Func<BasePlayer, ulong, int, bool>(TryOpenBackpackPage),
                    [nameof(SumBackpackItems)] = new Func<ulong, Dictionary<string, object>, int>(SumBackpackItems),
                    [nameof(CountBackpackItems)] = new Func<ulong, Dictionary<string, object>, int>(CountBackpackItems),
                    [nameof(TakeBackpackItems)] = new Func<ulong, Dictionary<string, object>, int, List<Item>, int>(TakeBackpackItems),
                    [nameof(MutateBackpackItems)] = new Func<ulong, Dictionary<string, object>, Dictionary<string, object>, int>(MutateBackpackItems),
                    [nameof(TryDepositBackpackItem)] = new Func<ulong, Item, bool>(TryDepositBackpackItem),
                    [nameof(PauseBackpackGatherMode)] = new Action<ulong, float>(PauseBackpackGatherMode),
                    [nameof(WriteBackpackContentsFromJson)] = new Action<ulong, string>(WriteBackpackContentsFromJson),
                    [nameof(ReadBackpackContentsAsJson)] = new Func<ulong, string>(ReadBackpackContentsAsJson),
                };
            }

            public void AddSubscriber(Plugin plugin, Dictionary<string, object> spec)
            {
                if (plugin == null)
                    throw new ArgumentNullException(nameof(plugin));

                if (spec == null)
                    throw new ArgumentNullException(nameof(spec));

                _plugin._subscriberManager.AddSubscriber(plugin, spec);
            }

            public void RemoveSubscriber(Plugin plugin)
            {
                if (plugin == null)
                    throw new ArgumentNullException(nameof(plugin));

                _plugin._subscriberManager.RemoveSubscriber(plugin);
            }

            public Dictionary<ulong, ItemContainer> GetExistingBackpacks()
            {
                return _backpackManager.GetAllCachedContainers();
            }

            public void EraseBackpack(ulong userId)
            {
                _backpackManager.TryEraseForPlayer(userId);
            }

            public DroppedItemContainer DropBackpack(BasePlayer player, List<DroppedItemContainer> collect)
            {
                var backpack = _backpackManager.GetBackpackIfExists(player.userID);
                if (backpack == null)
                    return null;

                return _backpackManager.Drop(player.userID, player.transform.position, collect);
            }

            public ulong GetBackpackOwnerId(ItemContainer container)
            {
                return _backpackManager.GetCachedBackpackForContainer(container)?.OwnerId ?? 0;
            }

            public bool IsBackpackLoaded(BasePlayer player)
            {
                return _backpackManager.GetBackpackIfCached(player.userID) != null;
            }

            public bool IsDynamicCapacityEnabled()
            {
                return _plugin._config.BackpackSize.DynamicSize.Enabled;
            }

            public int GetBackpackCapacity(BasePlayer player)
            {
                return _plugin._capacityManager.GetCapacity(player.userID, player.UserIDString);
            }
            
            public int GetBackpackCapacityById(ulong playerID, string playerIDString)
            {
                return _plugin._capacityManager.GetCapacity(playerID, playerIDString);
            }

            public int GetBackpackInitialCapacity(BasePlayer player)
            {
                return _plugin._capacityManager.GetInitialCapacity(player.userID, player.UserIDString);
            }

            public int GetBackpackMaxCapacity(BasePlayer player)
            {
                return _plugin._capacityManager.GetMaxCapacity(player.userID, player.UserIDString);
            }

            public int AddBackpackCapacity(BasePlayer player, int amount)
            {
                return _plugin._capacityManager.AddCapacity(player, amount);
            }

            public int SetBackpackCapacity(BasePlayer player, int capacity)
            {
                return _plugin._capacityManager.SetCapacity(player, capacity);
            }

            public bool IsBackpackGathering(BasePlayer player)
            {
                return _backpackManager.GetBackpackIfCached(player.userID)?.IsGathering ?? false;
            }

            public bool IsBackpackRetrieving(BasePlayer player)
            {
                return _backpackManager.GetBackpackIfCached(player.userID)?.IsRetrieving ?? false;
            }

            public ItemContainer GetBackpackContainer(ulong ownerId)
            {
                return _backpackManager.GetBackpackIfExists(ownerId)?.GetContainer(ensureContainer: true);
            }

            public int GetBackpackItemAmount(ulong ownerId, int itemId, ulong skinId)
            {
                var itemQuery = new ItemQuery { ItemId = itemId, SkinId = skinId };
                return _backpackManager.GetBackpackIfExists(ownerId)?.SumItems(ref itemQuery) ?? 0;
            }

            public bool TryOpenBackpack(BasePlayer player, ulong ownerId)
            {
                return _backpackManager.TryOpenBackpack(player, ownerId);
            }

            public bool TryOpenBackpackContainer(BasePlayer player, ulong ownerId, ItemContainer container)
            {
                return _backpackManager.TryOpenBackpackContainer(player, ownerId, container);
            }

            public bool TryOpenBackpackPage(BasePlayer player, ulong ownerId, int page)
            {
                return _backpackManager.TryOpenBackpackPage(player, ownerId, page);
            }

            public int SumBackpackItems(ulong ownerId, Dictionary<string, object> dict)
            {
                var itemQuery = ItemQuery.Parse(dict);
                return _backpackManager.GetBackpackIfExists(ownerId)?.SumItems(ref itemQuery) ?? 0;
            }

            public int CountBackpackItems(ulong ownerId, Dictionary<string, object> dict)
            {
                var backpack = _backpackManager.GetBackpackIfExists(ownerId);
                if (backpack == null)
                    return 0;

                if (dict == null)
                    return backpack.ItemCount;

                var itemQuery = ItemQuery.Parse(dict);
                return backpack.CountItems(ref itemQuery);
            }

            public int TakeBackpackItems(ulong ownerId, Dictionary<string, object> dict, int amount, List<Item> collect)
            {
                var itemQuery = ItemQuery.Parse(dict);
                return _backpackManager.GetBackpackIfExists(ownerId)?.TakeItems(ref itemQuery, amount, collect) ?? 0;
            }

            public int MutateBackpackItems(ulong ownerId, Dictionary<string, object> itemQueryDict, Dictionary<string, object> mutationRequestDict)
            {
                var itemQuery = ItemQuery.Parse(itemQueryDict);
                var mutationRequest = MutationRequest.Parse(mutationRequestDict);
                return _backpackManager.GetBackpackIfExists(ownerId)?.MutateItems(ref itemQuery, ref mutationRequest) ?? 0;
            }

            public bool TryDepositBackpackItem(ulong ownerId, Item item)
            {
                return _backpackManager.GetBackpack(ownerId).TryDepositItem(item);
            }

            public void PauseBackpackGatherMode(ulong ownerId, float duration)
            {
                _backpackManager.GetBackpackIfExists(ownerId)?.PauseGatherMode(duration);
            }

            public void WriteBackpackContentsFromJson(ulong ownerId, string json)
            {
                _backpackManager.GetBackpack(ownerId).WriteContentsFromJson(json);
            }

            public string ReadBackpackContentsAsJson(ulong ownerId)
            {
                return _backpackManager.GetBackpackIfExists(ownerId)?.SerializeContentsAsJson();
            }
        }

        [HookMethod(nameof(API_GetApi))]
        public Dictionary<string, object> API_GetApi()
        {
            return Api.ApiWrapper;
        }

        [HookMethod(nameof(API_AddSubscriber))]
        public void API_AddSubscriber(Plugin plugin, Dictionary<string, object> spec)
        {
            Api.AddSubscriber(plugin, spec);
        }

        [HookMethod(nameof(API_RemoveSubscriber))]
        public void API_RemoveSubscriber(Plugin plugin)
        {
            Api.RemoveSubscriber(plugin);
        }

        // Deprecated, only returns container for first page. Use higher level APIs instead.
        [HookMethod(nameof(API_GetExistingBackpacks))]
        public Dictionary<ulong, ItemContainer> API_GetExistingBackpacks()
        {
            return Api.GetExistingBackpacks();
        }

        [HookMethod(nameof(API_EraseBackpack))]
        public void API_EraseBackpack(ulong userId)
        {
            Api.EraseBackpack(userId);
        }
        [HookMethod(nameof(API_EraseBackpack))]
        public void API_EraseBackpack(EncryptedValue<ulong> userId)
        {
            Api.EraseBackpack(userId);
        }

        [HookMethod(nameof(API_DropBackpack))]
        public DroppedItemContainer API_DropBackpack(BasePlayer player, List<DroppedItemContainer> collect = null)
        {
            return Api.DropBackpack(player, collect);
        }

        [HookMethod(nameof(API_GetBackpackOwnerId))]
        public object API_GetBackpackOwnerId(ItemContainer container)
        {
            return ObjectCache.Get(Api.GetBackpackOwnerId(container));
        }

        [HookMethod(nameof(API_IsBackpackLoaded))]
        public object API_IsBackpackLoaded(BasePlayer player)
        {
            return ObjectCache.Get(Api.IsBackpackLoaded(player));
        }

        [HookMethod(nameof(API_IsDynamicCapacityEnabled))]
        public object API_IsDynamicCapacityEnabled(BasePlayer player)
        {
            return ObjectCache.Get(Api.IsDynamicCapacityEnabled());
        }

        [HookMethod(nameof(API_GetBackpackCapacity))]
        public object API_GetBackpackCapacity(BasePlayer player)
        {
            return ObjectCache.Get(Api.GetBackpackCapacity(player));
        }
        
        [HookMethod(nameof(API_GetBackpackCapacityById))]
        public object API_GetBackpackCapacityById(ulong playerID, string playerIDString)
        {
            return ObjectCache.Get(Api.GetBackpackCapacityById(playerID, playerIDString));
        }
        [HookMethod(nameof(API_GetBackpackCapacityById))]
        public object API_GetBackpackCapacityById(EncryptedValue<ulong> playerID, string playerIDString)
        {
            return ObjectCache.Get(Api.GetBackpackCapacityById(playerID, playerIDString));
        }

        [HookMethod(nameof(API_GetBackpackInitialCapacity))]
        public object API_GetBackpackInitialCapacity(BasePlayer player)
        {
            return ObjectCache.Get(Api.GetBackpackInitialCapacity(player));
        }

        [HookMethod(nameof(API_GetBackpackMaxCapacity))]
        public object API_GetBackpackMaxCapacity(BasePlayer player)
        {
            return ObjectCache.Get(Api.GetBackpackMaxCapacity(player));
        }

        [HookMethod(nameof(API_AddBackpackCapacity))]
        public object API_AddBackpackCapacity(BasePlayer player, int amount)
        {
            return ObjectCache.Get(Api.AddBackpackCapacity(player, amount));
        }

        [HookMethod(nameof(API_SetBackpackCapacity))]
        public object API_SetBackpackCapacity(BasePlayer player, int capacity)
        {
            return ObjectCache.Get(Api.SetBackpackCapacity(player, capacity));
        }

        [HookMethod(nameof(API_IsBackpackGathering))]
        public object API_IsBackpackGathering(BasePlayer player)
        {
            return ObjectCache.Get(Api.IsBackpackGathering(player));
        }

        [HookMethod(nameof(API_IsBackpackRetrieving))]
        public object API_IsBackpackRetrieving(BasePlayer player)
        {
            return ObjectCache.Get(Api.IsBackpackRetrieving(player));
        }

        // Deprecated, only returns container for first page. Use higher level APIs instead.
        [HookMethod(nameof(API_GetBackpackContainer))]
        public ItemContainer API_GetBackpackContainer(ulong ownerId)
        {
            return Api.GetBackpackContainer(ownerId);
        }
        [HookMethod(nameof(API_GetBackpackContainer))]
        public ItemContainer API_GetBackpackContainer(EncryptedValue<ulong> ownerId)
        {
            return Api.GetBackpackContainer(ownerId);
        }

        [HookMethod(nameof(API_GetBackpackItemAmount))]
        public int API_GetBackpackItemAmount(ulong ownerId, int itemId, ulong skinId = 0)
        {
            return Api.GetBackpackItemAmount(ownerId, itemId, skinId);
        }
        [HookMethod(nameof(API_GetBackpackItemAmount))]
        public int API_GetBackpackItemAmount(EncryptedValue<ulong> ownerId, int itemId, ulong skinId = 0)
        {
            return Api.GetBackpackItemAmount(ownerId, itemId, skinId);
        }

        [HookMethod(nameof(API_TryOpenBackpack))]
        public object API_TryOpenBackpack(BasePlayer player, ulong ownerId = 0)
        {
            return ObjectCache.Get(Api.TryOpenBackpack(player, ownerId));
        }
        [HookMethod(nameof(API_TryOpenBackpack))]
        public object API_TryOpenBackpack(BasePlayer player, EncryptedValue<ulong> ownerId = default)
        {
            return ObjectCache.Get(Api.TryOpenBackpack(player, ownerId));
        }

        [HookMethod(nameof(API_TryOpenBackpackContainer))]
        public object API_TryOpenBackpackContainer(BasePlayer player, ulong ownerId, ItemContainer container)
        {
            return ObjectCache.Get(Api.TryOpenBackpackContainer(player, ownerId, container));
        }
        [HookMethod(nameof(API_TryOpenBackpackContainer))]
        public object API_TryOpenBackpackContainer(BasePlayer player, EncryptedValue<ulong> ownerId, ItemContainer container)
        {
            return ObjectCache.Get(Api.TryOpenBackpackContainer(player, ownerId, container));
        }

        [HookMethod(nameof(API_TryOpenBackpackPage))]
        public object API_TryOpenBackpackPage(BasePlayer player, ulong ownerId = 0, int page = 0)
        {
            return ObjectCache.Get(Api.TryOpenBackpackPage(player, ownerId, page));
        }
        [HookMethod(nameof(API_TryOpenBackpackPage))]
        public object API_TryOpenBackpackPage(BasePlayer player, EncryptedValue<ulong> ownerId = default, int page = 0)
        {
            return ObjectCache.Get(Api.TryOpenBackpackPage(player, ownerId, page));
        }

        [HookMethod(nameof(API_SumBackpackItems))]
        public object API_SumBackpackItems(ulong ownerId, Dictionary<string, object> dict)
        {
            return ObjectCache.Get(Api.SumBackpackItems(ownerId, dict));
        }
        [HookMethod(nameof(API_SumBackpackItems))]
        public object API_SumBackpackItems(EncryptedValue<ulong> ownerId, Dictionary<string, object> dict)
        {
            return ObjectCache.Get(Api.SumBackpackItems(ownerId, dict));
        }

        [HookMethod(nameof(API_CountBackpackItems))]
        public object API_CountBackpackItems(ulong ownerId, Dictionary<string, object> dict)
        {
            return ObjectCache.Get(Api.CountBackpackItems(ownerId, dict));
        }
        [HookMethod(nameof(API_CountBackpackItems))]
        public object API_CountBackpackItems(EncryptedValue<ulong> ownerId, Dictionary<string, object> dict)
        {
            return ObjectCache.Get(Api.CountBackpackItems(ownerId, dict));
        }

        [HookMethod(nameof(API_TakeBackpackItems))]
        public object API_TakeBackpackItems(ulong ownerId, Dictionary<string, object> dict, int amount, List<Item> collect)
        {
            return ObjectCache.Get(Api.TakeBackpackItems(ownerId, dict, amount, collect));
        }
        [HookMethod(nameof(API_TakeBackpackItems))]
        public object API_TakeBackpackItems(EncryptedValue<ulong> ownerId, Dictionary<string, object> dict, int amount, List<Item> collect)
        {
            return ObjectCache.Get(Api.TakeBackpackItems(ownerId, dict, amount, collect));
        }

        [HookMethod(nameof(API_MutateBackpackItems))]
        public object API_MutateBackpackItems(ulong ownerId, Dictionary<string, object> itemQueryDict, Dictionary<string, object> mutationRequestDict)
        {
            return ObjectCache.Get(Api.MutateBackpackItems(ownerId, itemQueryDict, mutationRequestDict));
        }
        [HookMethod(nameof(API_MutateBackpackItems))]
        public object API_MutateBackpackItems(EncryptedValue<ulong> ownerId, Dictionary<string, object> itemQueryDict, Dictionary<string, object> mutationRequestDict)
        {
            return ObjectCache.Get(Api.MutateBackpackItems(ownerId, itemQueryDict, mutationRequestDict));
        }

        [HookMethod(nameof(API_TryDepositBackpackItem))]
        public object API_TryDepositBackpackItem(ulong ownerId, Item item)
        {
            return ObjectCache.Get(Api.TryDepositBackpackItem(ownerId, item));
        }
        [HookMethod(nameof(API_TryDepositBackpackItem))]
        public object API_TryDepositBackpackItem(EncryptedValue<ulong> ownerId, Item item)
        {
            return ObjectCache.Get(Api.TryDepositBackpackItem(ownerId, item));
        }

        [HookMethod(nameof(API_PauseBackpackGatherMode))]
        public void API_PauseBackpackGatherMode(ulong ownerId, float duration)
        {
            Api.PauseBackpackGatherMode(ownerId, duration);
        }
        [HookMethod(nameof(API_PauseBackpackGatherMode))]
        public void API_PauseBackpackGatherMode(EncryptedValue<ulong> ownerId, float duration)
        {
            Api.PauseBackpackGatherMode(ownerId, duration);
        }

        [HookMethod(nameof(API_WriteBackpackContentsFromJson))]
        public void API_WriteBackpackContentsFromJson(ulong ownerId, string json)
        {
            Api.WriteBackpackContentsFromJson(ownerId, json);
        }
        [HookMethod(nameof(API_WriteBackpackContentsFromJson))]
        public void API_WriteBackpackContentsFromJson(EncryptedValue<ulong> ownerId, string json)
        {
            Api.WriteBackpackContentsFromJson(ownerId, json);
        }

        [HookMethod(nameof(API_ReadBackpackContentsAsJson))]
        public object API_ReadBackpackContentsAsJson(ulong ownerId)
        {
            return Api.ReadBackpackContentsAsJson(ownerId);
        }
        [HookMethod(nameof(API_ReadBackpackContentsAsJson))]
        public object API_ReadBackpackContentsAsJson(EncryptedValue<ulong> ownerId)
        {
            return Api.ReadBackpackContentsAsJson(ownerId);
        }

        #endregion

        #region Exposed Hooks

        private static class ExposedHooks
        {
            public static object CanOpenBackpack(BasePlayer looter, ulong ownerId)
            {
                return Interface.CallHook("CanOpenBackpack", looter, ObjectCache.Get(ownerId));
            }

            public static void OnBackpackClosed(BasePlayer looter, ulong ownerId, ItemContainer container)
            {
                Interface.CallHook("OnBackpackClosed", looter, ObjectCache.Get(ownerId), container);
            }

            public static void OnBackpackOpened(BasePlayer looter, ulong ownerId, ItemContainer container)
            {
                Interface.CallHook("OnBackpackOpened", looter, ObjectCache.Get(ownerId), container);
            }

            public static object CanDropBackpack(ulong ownerId, Vector3 position)
            {
                return Interface.CallHook("CanDropBackpack", ObjectCache.Get(ownerId), position);
            }

            public static void OnBackpackDropped(ulong ownerId, List<DroppedItemContainer> droppedBackpackList)
            {
                Interface.CallHook("OnBackpackDropped", ownerId, droppedBackpackList);
            }

            public static object CanEraseBackpack(ulong ownerId)
            {
                return Interface.CallHook("CanEraseBackpack", ObjectCache.Get(ownerId));
            }

            public static object CanBackpackAcceptItem(ulong ownerId, ItemContainer container, Item item)
            {
                return Interface.CallHook("CanBackpackAcceptItem", ObjectCache.Get(ownerId), container, item);
            }
        }

        #endregion

        #region Commands

        [Command("backpack", "backpack.open")]
        private void BackpackOpenCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyCanInteract(player, out var basePlayer)
                || !VerifyHasPermission(player, UsagePermission))
                return;

            OpenBackpack(
                basePlayer,
                IsKeyBindArg(args.LastOrDefault()),
                ParsePageArg(args.FirstOrDefault()),
                wrapAround: false
            );
        }

        [Command("backpack.next")]
        private void BackpackNextCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyCanInteract(player, out var basePlayer)
                || !VerifyHasPermission(player, UsagePermission))
                return;

            OpenBackpack(
                basePlayer,
                IsKeyBindArg(args.LastOrDefault())
            );
        }

        [Command("backpack.previous", "backpack.prev")]
        private void BackpackPreviousCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyCanInteract(player, out var basePlayer)
                || !VerifyHasPermission(player, UsagePermission))
                return;

            OpenBackpack(
                basePlayer,
                IsKeyBindArg(args.LastOrDefault()),
                forward: false
            );
        }

        [Command("backpack.fetch")]
        private void BackpackFetchCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyCanInteract(player, out var basePlayer)
                || !VerifyHasPermission(player, FetchPermission))
                return;

            if (args.Length < 2)
            {
                ReplyToPlayer(player, LangEntry.BackpackFetchSyntax);
                return;
            }

            if (!VerifyCanOpenBackpack(basePlayer, basePlayer.userID))
                return;

            if (!VerifyValidItem(player, args[0], out var itemDefinition))
                return;

            if (!int.TryParse(args[1], out var desiredAmount) || desiredAmount < 1)
            {
                ReplyToPlayer(player, LangEntry.InvalidItemAmount);
                return;
            }

            var itemLocalizedName = itemDefinition.displayName.translated;
            var backpack = _backpackManager.GetBackpack(basePlayer.userID);

            var itemQuery = new ItemQuery { ItemDefinition = itemDefinition };

            var quantityInBackpack = backpack.SumItems(ref itemQuery);
            if (quantityInBackpack == 0)
            {
                ReplyToPlayer(player, LangEntry.ItemNotInBackpack, itemLocalizedName);
                return;
            }

            if (desiredAmount > quantityInBackpack)
            {
                desiredAmount = quantityInBackpack;
            }

            var amountTransferred = backpack.FetchItems(basePlayer, ref itemQuery, desiredAmount);
            if (amountTransferred <= 0)
            {
                ReplyToPlayer(player, LangEntry.FetchFailed, itemLocalizedName);
                return;
            }

            ReplyToPlayer(player, LangEntry.ItemsFetched, amountTransferred, itemLocalizedName);
        }

        [Command("backpack.erase")]
        private void EraseBackpackCommand(IPlayer player, string cmd, string[] args)
        {
            if (!player.IsServer)
                return;

            if (args.Length < 1 || !ulong.TryParse(args[0], out var userId))
            {
                player.Reply($"Syntax: {cmd} <id>");
                return;
            }

            if (!_backpackManager.TryEraseForPlayer(userId))
            {
                LogWarning($"Player {userId.ToString()} has no backpack to erase.");
                return;
            }

            LogWarning($"Erased backpack for player {userId.ToString()}.");
        }

        [Command("backpack.wipeall")]
        private void WipeAllBackpacksCommand(IPlayer player, string cmd, string[] args)
        {
            if (!player.IsServer)
                return;

            PerformBackpackWipe("All backpacks wiped by command");
        }

        [Command("viewbackpack")]
        private void ViewBackpackCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyCanInteract(player, out var basePlayer)
                || !VerifyHasAnyPermission(player, AdminPermission, AdminViewPermission, AdminEditPermission))
                return;

            if (args.Length < 1)
            {
                ReplyToPlayer(player, LangEntry.ViewBackpackSyntax);
                return;
            }

            if (!VerifyTargetPlayer(player, args[0], out var targetPlayerId, out var targetPlayerIdString))
                return;

            if (permission.UserHasPermission(targetPlayerIdString, AdminProtectedPermission))
            {
                ReplyToPlayer(player, LangEntry.ViewBackpackProtected);
                return;
            }

            OpenBackpack(
                basePlayer,
                IsKeyBindArg(args.LastOrDefault()),
                ParsePageArg(args.ElementAtOrDefault(1)),
                desiredOwnerId: targetPlayerId
            );
        }

        // Alias for older versions of Player Administration (which should ideally not be calling this method directly).
        private void ViewBackpack(BasePlayer player, string cmd, string[] args) =>
            ViewBackpackCommand(player.IPlayer, cmd, args);

        [Command("backpack.addsize")]
        private void AddBackpackCapacityCommand(IPlayer player, string cmd, string[] args)
        {
            if (!VerifyHasAnyPermission(player, AdminPermission, AdminResizePermission))
                return;

            if (args.Length < 2 || !int.TryParse(args[1], out var amount))
            {
                ReplyToPlayer(player, LangEntry.BackpackCapacitySyntax, cmd);
                return;
            }

            if (!VerifyTargetPlayer(player, args[0], out var targetPlayerId, out var targetPlayerIdString)
                || !VerifyDynamicCapacityEnabled(player))
                return;

            var newCapacity = _capacityManager.AddCapacity(targetPlayerId, targetPlayerIdString, amount);
            ReplyToPlayer(player, LangEntry.ChangeCapacitySuccess, targetPlay
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху