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

FREE ChestStackMultiplier : 1.6.1 1.6.1

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json;
using UnityEngine;
using Pool = Facepunch.Pool;
namespace Oxide.Plugins {
    [Info("Chest Stack Multiplier", "MON@H", "1.6.1")]
    [Description("Higher stack sizes in storage containers.")]
    public class ChestStackMultiplier : RustPlugin {
#region Variables
        private const string PermissionUseShift = "cheststackmultiplier.useshift";
        private static readonly object _true = true;
        private readonly Hash<ulong, float> _cacheMultipliers = new();
        private readonly HashSet<ulong> _cacheBackpackContainers = new();
        private readonly HashSet<ulong> _cacheBackpackEntities = new();
        private ItemContainer _targetContainer;
        private uint _backpackPrefabID;
        private uint _playerPrefabID;
#endregion Variables
#region Initialization
        private void Init() => HooksUnsubscribe();
        private void OnServerInitialized() {
            RegisterPermissions();
            CachePrefabIDs();
            CacheMultipliers();
            HooksSubscribe();
        }
#endregion Initialization
#region Configuration
        private PluginConfig _pluginConfig;
        public class PluginConfig {
            [JsonProperty(PropertyName = "Default Multiplier for new containers")]
            [DefaultValue(1f)]
            public float DefaultMultiplier {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Containers list (PrefabName: multiplier)")]
            public SortedDictionary<string, float> ContainerMultipliers {
                get;
                set;
            }
        }
        protected override void LoadDefaultConfig() => PrintWarning("Loading Default Config");
        protected override void LoadConfig() {
            base.LoadConfig();
            Config.Settings.DefaultValueHandling = DefaultValueHandling.Populate;
            _pluginConfig = AdditionalConfig(Config.ReadObject<PluginConfig>());
            Config.WriteObject(_pluginConfig);
        }
        public PluginConfig AdditionalConfig(PluginConfig config) {
            if (config.DefaultMultiplier <= 0) {
                PrintWarning("LoadConfig: Default Multiplier can't be less than or equal to 0, resetting to 1");
                config.DefaultMultiplier = 1f;
            }
            if (config.ContainerMultipliers == null) {
                config.ContainerMultipliers = new();
                foreach (ItemDefinition def in ItemManager.GetItemDefinitions()) {
                    BoxStorage entity = def.GetComponent<ItemModDeployable>()?.entityPrefab.Get().GetComponent<BoxStorage>();
                    if (!entity || config.ContainerMultipliers.ContainsKey(entity.PrefabName)) {
                        continue;
                    }
                    config.ContainerMultipliers[entity.PrefabName] = config.DefaultMultiplier;
                }
            }
            List<string> invalidValues = Pool.GetList<string>();
            foreach (KeyValuePair<string, float> containerMultiplier in config.ContainerMultipliers) {
                if (containerMultiplier.Value > 0) {
                    continue;
                }
                PrintWarning($"LoadConfig: {containerMultiplier.Key} Multiplier can't be less than or equal to 0, resetting to default");
                invalidValues.Add(containerMultiplier.Key);
            }
            foreach (string invalidValue in invalidValues) {
                config.ContainerMultipliers[invalidValue] = config.DefaultMultiplier;
            }
            Pool.FreeList(ref invalidValues);
            return config;
        }
#endregion Configuration
#region Oxide Hooks
        private object OnMaxStackable(Item item) {
            if (item.info.stackable == 1 || item.info.itemType == ItemContainer.ContentsType.Liquid) {
                return null;
            }
            BaseEntity entity;
            if (_targetContainer != null) {
                entity = _targetContainer.GetEntityOwner() ?? _targetContainer.GetOwnerPlayer();
                if (entity.IsValid()) {
                    _targetContainer = null;
                    float stackMultiplier = GetStackMultiplier(entity);
                    if (stackMultiplier == 1f) {
                        return null;
                    }
                    return Mathf.FloorToInt(stackMultiplier * item.info.stackable);
                }
            }
            entity = item.GetEntityOwner() ?? item.GetOwnerPlayer();
            if (entity.IsValid()) {
                float stackMultiplier;
                if (entity.prefabID == _playerPrefabID && !item.parent.HasFlag(ItemContainer.Flag.IsPlayer)) {
                    stackMultiplier = _cacheMultipliers[_backpackPrefabID];
                }
                else {
                    stackMultiplier = GetStackMultiplier(entity);
                }
                if (stackMultiplier != 1f) {
                    return Mathf.FloorToInt(stackMultiplier * item.info.stackable);
                }
            }
            return null;
        }
        private object CanMoveItem(Item movedItem, PlayerInventory playerInventory, ItemContainerId targetContainerID, int targetSlot, int amount) {
            if (movedItem == null || playerInventory == null) {
                return null;
            }
            BasePlayer player = playerInventory.baseEntity;
            if (!player.IsValid()) {
                return null;
            }
            BaseEntity sourceEntity = movedItem.GetEntityOwner() ?? movedItem.GetOwnerPlayer();
            if (IsExcluded(sourceEntity, player)) {
                return null;
            }
            if (targetContainerID.Value == 0) {
                //Moving From Player Inventory
                if (sourceEntity == player) {
                    if (playerInventory.loot.containers.Count > 0) {
                        targetContainerID.Value = playerInventory.loot.containers[0].uid.Value;
                        //Puts($"Moving item {movedItem} into looting container {targetContainerID}");
                    }
                    else {
                        return null;
                        //targetContainerID = player.GetIdealContainer(player, movedItem, false);
                        //Puts($"Moving item {movedItem} to another player inventory container {targetContainerID}");
                    }
                }
                else if (sourceEntity == playerInventory.loot.entitySource) {
                    targetContainerID = playerInventory.containerMain.uid;
                    //Puts($"Moving item {movedItem} into player inventory from container {targetContainerID}");
                }
            }
            ItemContainer targetContainer = playerInventory.FindContainer(targetContainerID);
            if (targetContainer == null) {
                return null;
            }
            BaseEntity targetEntity = targetContainer.GetEntityOwner() ?? targetContainer.GetOwnerPlayer();
            if (sourceEntity == targetEntity || IsExcluded(targetEntity, player)) {
                return null;
            }
            ItemContainer lootContainer = playerInventory.loot?.FindContainer(targetContainerID);
            _targetContainer = targetContainer;
            //Puts($"TargetSlot {targetSlot} Amount {amount} TargetContainer {targetContainerID}");
            // Right-Click Overstack into Player Inventory
            if (targetSlot == -1) {
                if (lootContainer == null) {
                    if (movedItem.amount > movedItem.info.stackable) {
                        int loops = 1;
                        if (IsUsingShift(player)) {
                            loops = Mathf.CeilToInt((float)movedItem.amount / movedItem.info.stackable);
                        }
                        for (int i = 0; i < loops; i++) {
                            if (movedItem.amount <= movedItem.info.stackable) {
                                if (targetContainer != null) {
                                    movedItem.MoveToContainer(targetContainer);
                                }
                                else {
                                    playerInventory.GiveItem(movedItem);
                                }
                                break;
                            }
                            Item itemToMove = movedItem.SplitItem(movedItem.info.stackable);
                            bool moved;
                            if (targetContainer != null) {
                                moved = itemToMove.MoveToContainer(targetContainer, targetSlot);
                            }
                            else {
                                moved = playerInventory.GiveItem(itemToMove);
                            }
                            if (moved == false) {
                                movedItem.amount += itemToMove.amount;
                                itemToMove.Remove();
                                break;
                            }
                            movedItem?.MarkDirty();
                        }
                        playerInventory.ServerUpdate(0f);
                        return _true;
                    }
                }
                // Shift Right click into storage container
                else {
                    if (IsUsingShift(player)) {
                        //Puts($"Shift Right click into storage container {lootContainer}");
                        List<Item> itemsToMove = Pool.GetList<Item>();
                        int i = 0;
                        foreach (Item item in playerInventory.containerMain.itemList) {
                            if (item.info.itemid == movedItem.info.itemid && item != movedItem) {
                                itemsToMove.Add(item);
                            }
                        }
                        foreach (Item item in playerInventory.containerBelt.itemList) {
                            if (item.info.itemid == movedItem.info.itemid && item != movedItem) {
                                itemsToMove.Add(item);
                            }
                        }
                        foreach (Item item in itemsToMove) {
                            if (!item.MoveToContainer(lootContainer)) {
                                break;
                            }
                            i++;
                        }
                        Pool.FreeList(ref itemsToMove);
                        if (i > 0) {
                            playerInventory.ServerUpdate(0f);
                            return null;
                        }
                    }
                }
            }
            // Moving Overstacks Around In Chest
            if (amount > movedItem.info.stackable && lootContainer != null) {
                Item targetItem = targetContainer.GetSlot(targetSlot);
                if (targetItem == null) {
                    // Split item into chest
                    if (amount < movedItem.amount) {
                        ItemHelper.SplitMoveItem(movedItem, amount, targetContainer, targetSlot);
                    }
                    else {
                        // Moving items when amount > info.stacksize
                        movedItem.MoveToContainer(targetContainer, targetSlot);
                    }
                }
                else {
                    if (!targetItem.CanStack(movedItem) && amount == movedItem.amount) {
                        // Swapping positions of items
                        ItemHelper.SwapItems(movedItem, targetItem);
                    }
                    else {
                        if (amount < movedItem.amount) {
                            ItemHelper.SplitMoveItem(movedItem, amount, playerInventory);
                        }
                        else {
                            movedItem.MoveToContainer(targetContainer, targetSlot);
                        }
                        // Stacking items when amount > info.stacksize
                    }
                }
                playerInventory.ServerUpdate(0f);
                return _true;
            }
            // Prevent Moving Overstacks To Inventory
            if (lootContainer != null) {
                Item targetItem = targetContainer.GetSlot(targetSlot);
                if (targetItem != null) {
                    if (movedItem.GetOwnerPlayer() == player) {
                        if (!movedItem.CanStack(targetItem)) {
                            if (targetItem.amount > targetItem.info.stackable) {
                                return _true;
                            }
                        }
                    }
                }
            }
            return null;
        }
        // Covers dropping overstacks from chests onto the ground
        private void OnItemDropped(Item item, BaseEntity entity) {
            if (item == null || !entity.IsValid()) {
                return;
            }
            item.RemoveFromContainer();
            int stackSize = item.MaxStackable();
            if (item.amount > stackSize) {
                int loops = Mathf.FloorToInt((float)item.amount / stackSize);
                if (loops > 20) {
                    return;
                }
                for (int i = 0; i < loops; i++) {
                    if (item.amount <= stackSize) {
                        break;
                    }
                    Item splitItem = item.SplitItem(stackSize);
                    splitItem?.Drop(entity.transform.position, entity.GetDropVelocity() + Vector3Ex.Range(-1f, 1f));
                }
            }
        }
        private void OnBackpackOpened(BasePlayer player, ulong backpackOwnerID, ItemContainer backpackContainer) {
            try {
                if (backpackContainer != null && !_cacheBackpackContainers.Contains(backpackContainer.uid.Value)) {
                    CacheAddBackpack(backpackContainer);
                }
            }
            catch (System.Exception ex) {
                PrintError($"OnBackpackOpened threw exception\n:{ex}");
                throw;
            }
        }
#endregion Oxide Hooks
#region Core Methods
        public void CachePrefabIDs() {
            _playerPrefabID = StringPool.Get("assets/prefabs/player/player.prefab");
            if (!_pluginConfig.ContainerMultipliers.ContainsKey("Backpack")) {
                _pluginConfig.ContainerMultipliers["Backpack"] = _pluginConfig.DefaultMultiplier;
                Config.WriteObject(_pluginConfig);
            }
            _backpackPrefabID = StringPool.closest;
            while (StringPool.toString.ContainsKey(_backpackPrefabID)) {
                _backpackPrefabID++;
            }
        }
        public void CacheMultipliers() {
            foreach (KeyValuePair<string, float> container in _pluginConfig.ContainerMultipliers) {
                if (container.Key == "Backpack") {
                    _cacheMultipliers[_backpackPrefabID] = _pluginConfig.ContainerMultipliers["Backpack"];
                }
                else {
                    uint id = StringPool.Get(container.Key);
                    if (id > 0) {
                        _cacheMultipliers[id] = container.Value;
                    }
                }
            }
        }
        public void CacheAddBackpack(ItemContainer itemContainer) {
            BaseEntity baseEntity = itemContainer.GetEntityOwner();
            if (baseEntity.IsValid() && !_cacheBackpackEntities.Contains(baseEntity.net.ID.Value)) {
                _cacheBackpackContainers.Add(itemContainer.uid.Value);
                _cacheBackpackEntities.Add(baseEntity.net.ID.Value);
            }
        }
        public bool IsExcluded(BaseEntity entity, BasePlayer player) => !entity.IsValid() || entity.HasFlag(BaseEntity.Flags.Locked) || entity is BigWheelBettingTerminal || entity is ShopFront || entity is VendingMachine vendingMachine && !vendingMachine.PlayerBehind(player);
        public bool IsUsingShift(BasePlayer player) => permission.UserHasPermission(player.UserIDString, PermissionUseShift) && player.serverInput.IsDown(BUTTON.SPRINT);
        public class ItemHelper {
            public static bool SplitMoveItem(Item item, int amount, ItemContainer targetContainer, int targetSlot) {
                Item splitItem = item.SplitItem(amount);
                if (splitItem == null) {
                    return false;
                }
                if (!splitItem.MoveToContainer(targetContainer, targetSlot)) {
                    item.amount += splitItem.amount;
                    splitItem.Remove();
                }
                return true;
            }
            public static bool SplitMoveItem(Item item, int amount, PlayerInventory inventory) {
                Item splitItem = item.SplitItem(amount);
                if (splitItem == null) {
                    return false;
                }
                if (!inventory.GiveItem(splitItem)) {
                    item.amount += splitItem.amount;
                    splitItem.Remove();
                }
                return true;
            }
            public static void SwapItems(Item item1, Item item2) {
                ItemContainer container1 = item1.parent;
                ItemContainer container2 = item2.parent;
                int slot1 = item1.position;
                int slot2 = item2.position;
                item1.RemoveFromContainer();
                item2.RemoveFromContainer();
                item1.MoveToContainer(container2, slot2);
                item2.MoveToContainer(container1, slot1);
            }
        }
        public float GetStackMultiplier(BaseEntity entity) {
            switch (entity) {
                case LootContainer : case BaseCorpse : case BasePlayer : return 1f;
            }
            if (_cacheBackpackEntities.Contains(entity.net.ID.Value)) {
                return _cacheMultipliers[_backpackPrefabID];
            }
            float multiplier = _cacheMultipliers[entity.prefabID];
            if (multiplier == 0) {
                if (!_pluginConfig.ContainerMultipliers.TryGetValue(entity.PrefabName, out multiplier)) {
                    multiplier = _pluginConfig.DefaultMultiplier;
                    _pluginConfig.ContainerMultipliers[entity.PrefabName] = multiplier;
                    Config.WriteObject(_pluginConfig);
                }
                _cacheMultipliers[entity.prefabID] = multiplier;
            }
            return multiplier;
        }
#endregion Core Methods
#region Helpers
        public void HooksUnsubscribe() {
            Unsubscribe(nameof(CanMoveItem));
            Unsubscribe(nameof(OnBackpackOpened));
            Unsubscribe(nameof(OnItemDropped));
            Unsubscribe(nameof(OnMaxStackable));
        }
        public void HooksSubscribe() {
            Subscribe(nameof(CanMoveItem));
            Subscribe(nameof(OnBackpackOpened));
            Subscribe(nameof(OnItemDropped));
            Subscribe(nameof(OnMaxStackable));
        }
        public void RegisterPermissions() => permission.RegisterPermission(PermissionUseShift, this);
#endregion Helpers
    }
}

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