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

FREE HomeRecycler : 2.0.3 2.0.3

Нет прав для скачивания
C#:
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;

using Random = UnityEngine.Random;

namespace Oxide.Plugins
{
    [Info("HomeRecycler", "wazzzup", "2.0.3")]
    [Description("Allows to have Recycler at home")]
    class HomeRecycler : RustPlugin
    {
        [PluginReference] Plugin Friends;
        
        private readonly Dictionary<uint, ulong> startedRecyclers = new Dictionary<uint, ulong>();
        private readonly Dictionary<int, KeyValuePair<string, int>> itemsNeededToCraft = new Dictionary<int, KeyValuePair<string, int>>();
        private readonly Dictionary<BasePlayer, RecyclerEntity> pickupRecyclers = new Dictionary<BasePlayer, RecyclerEntity>();
       
        #region Fields
        private int recyclerItemId;

        private const ulong RECYCLER_SKIN_ID = 1321253094UL;

        private const string PERMISSION_GENERIC = "homerecycler.{0}";
        private const string PERMISSION_CANGET = "homerecycler.canget";
        private const string PERMISSION_CANCRAFT = "homerecycler.cancraft";
        private const string PERMISSION_IGNORE_COOLDOWN = "homerecycler.ignorecooldown";
        private const string PERMISSION_IGNORE_CRAFT_COOLDOWN = "homerecycler.ignorecraftcooldown";

        private static readonly DateTime Epoch = new DateTime(1970, 1, 1);
        #endregion

        #region Oxide Hooks
        private void Init()
        {
            LoadData();
            
            Unsubscribe(nameof(OnLootSpawn));
            
            if (!configData.allowRepair && !configData.allowPickupByHammerHit)
                Unsubscribe(nameof(OnHammerHit));
            
            if (!configData.trackStacking)
            {
                Unsubscribe(nameof(CanCombineDroppedItem));
                Unsubscribe(nameof(CanStackItem));
                Unsubscribe(nameof(OnItemSplit));
            }

            if (configData.useSpawning)
            {
                cmd.AddChatCommand(configData.chatCommand, this, "cmdRec");
            }
            else PrintWarning($"Spawning/getting by command {configData.chatCommand} is disabled, check config if needed");

            if (configData.useCrafting)
            {
                if (configData.itemsNeededToCraft.Count < 1)
                {
                    PrintWarning("no items set to craft, check config");
                }
                else
                {
                    cmd.AddChatCommand(configData.craftCommand, this, "cmdCraft");
                }
            }
            else PrintWarning($"Crafting by command {configData.craftCommand} is disabled, check config if needed");

            RegisterPermissions();
        }

        private void OnServerInitialized()
        {
            recyclerItemId = ItemManager.FindItemDefinition(configData.recyclerItemName).itemid;

            Recycler[] allobjects = UnityEngine.Object.FindObjectsOfType<Recycler>();
            foreach (Recycler r in allobjects)
            {
                if (r.OwnerID != 0)
                {
                    if (!r.gameObject.GetComponent<RecyclerEntity>())
                        r.gameObject.AddComponent<RecyclerEntity>();
                    
                    ApplyRecyclerSettings(r, true);
                }
            }

            if (configData.spawnInLoot)
            {
                bool hasChanged = false;
                foreach (LootContainer container in UnityEngine.Resources.FindObjectsOfTypeAll<LootContainer>())
                {
                    ConfigData.Loot l;
                    if (!configData.FindLootContainer(container.ShortPrefabName, out l))
                    {
                        configData.loot.Add(new ConfigData.Loot { containerName = container.ShortPrefabName });
                        hasChanged = true;
                    }
                }
                
                if (hasChanged)
                    SaveConfig();

                Subscribe(nameof(OnLootSpawn));
                
                foreach (LootContainer container in UnityEngine.Object.FindObjectsOfType<LootContainer>())
                    container.Invoke(container.SpawnLoot, Random.Range(0f, 10f));
            }

            if (configData.useCrafting)
            {
                foreach (KeyValuePair<string, int> kvp in configData.itemsNeededToCraft)
                {
                    ItemDefinition itemDefinition = ItemManager.FindItemDefinition(kvp.Key);
                    if (!itemDefinition)
                    {
                        PrintWarning($"Invalid shortname for crafting item {kvp.Key}");
                        continue;
                    }

                    itemsNeededToCraft[itemDefinition.itemid] = new KeyValuePair<string, int>(itemDefinition.displayName.english, kvp.Value);
                }
            }
        }
        
        private void OnNewSave()
        {
            pluginData = new PluginData();
            SaveData();
        }

        private void OnServerSave() => SaveData();
        
        private void OnEntityBuilt(Planner plan, GameObject obj)
        {
            BaseEntity entity = obj.GetComponent<BaseEntity>();
            if (entity && entity.ShortPrefabName == configData.recyclerShortPrefabName && entity.skinID == RECYCLER_SKIN_ID)
            {
                BasePlayer player = plan.GetOwnerPlayer();
                if (!configData.allowDeployOnGround && player.net.connection.authLevel < 2)
                {
                    if (!IsOnBuildingBlock(entity))
                    {
                        GiveRecycler(player);
                        SendMsg(player, "place on construction");
                        
                        NextTick(() =>
                        {
                            if (entity && !entity.IsDestroyed)
                                entity.Kill();
                        });
                        return;
                    }
                }

                Recycler recycler = GameManager.server.CreateEntity("assets/bundled/prefabs/static/recycler_static.prefab", entity.transform.position, entity.transform.rotation) as Recycler;
                
                recycler.OwnerID = configData.adminSpawnsPublicRecycler && player.net.connection.authLevel == 2 ? 0UL : player.userID;
                recycler.Spawn();
                
                NextTick(() =>
                {
                    if (entity && !entity.IsDestroyed)
                        entity.Kill();
                });
                
                recycler.gameObject.AddComponent<RecyclerEntity>();
                ApplyRecyclerSettings(recycler);
            }
        }
        
        private void OnHammerHit(BasePlayer player, HitInfo info)
        {
            if (!player || info == null || !info.HitEntity) 
                return;
            
            RecyclerEntity rec = info.HitEntity.GetComponent<RecyclerEntity>();
            if (rec && rec.OwnerID != 0)
            {
                if (configData.allowRepair)
                    ShowUIHealth(player, $"{(int)info.HitEntity.Health()} / {(int)info.HitEntity.MaxHealth()}");
                

                if (configData.allowPickupByHammerHit)
                {
                    if (pickupRecyclers.ContainsKey(player))
                        return;

                    if (configData.restrictUseByCupboard && !player.CanBuild())
                    {
                        SendMsg(player, "buldingBlocked");
                        return;
                    }

                    if (configData.pickupOnlyOwnerFriends && !(rec.OwnerID == player.userID || (bool) (Friends?.Call("AreFriends", rec.OwnerID, player.userID) ?? false)))
                    {
                        SendMsg(player, "cant pick");
                        return;
                    }

                    pickupRecyclers.Add(player, rec);
                    
                    timer.In(30f, () =>
                    {
                        if (!player) 
                            return;
                        
                        if (pickupRecyclers.ContainsKey(player))
                        {
                            pickupRecyclers.Remove(player);
                        }
                    });
                    
                    if (configData.allowRepair && info.HitEntity.Health() < info.HitEntity.MaxHealth())
                    {
                        SendMsg(player, "repair first");
                        return;
                    }

                    ShowUIPickup(player);
                }
            }
        }

        private void OnRecyclerToggle(Recycler recycler, BasePlayer player)
        {
            if (recycler.IsOn() || (recycler.OwnerID == 0 && !configData.canChangePublicRecyclerParams))
                return;
            
            if (configData.restrictUseByCupboard && recycler.OwnerID != 0 && !player.CanBuild())
            {
                NextTick(() =>
                {
                    SendMsg(player, "buldingBlocked");
                    recycler.StopRecycling();
                });
                return;
            }

            startedRecyclers[recycler.net.ID] = player.userID;
            NextTick(() =>
            {
                if (!recycler.IsOn()) 
                    return;
                
                foreach (KeyValuePair<string, ConfigData.Rates> perm in configData.PermissionsRates)
                {
                    if (permission.UserHasPermission(player.UserIDString, string.Format(PERMISSION_GENERIC, perm.Key)))
                    {
                        recycler.CancelInvoke(recycler.RecycleThink);
                        recycler.InvokeRepeating(recycler.RecycleThink, perm.Value.Speed, perm.Value.Speed);
                        return;
                    }
                }

                if (configData.DefaultRates.Speed != 5f)
                {
                    recycler.CancelInvoke(recycler.RecycleThink);
                    recycler.InvokeRepeating(recycler.RecycleThink, configData.DefaultRates.Speed, configData.DefaultRates.Speed);
                }
            });
        }

        private object OnItemRecycle(Item item, Recycler recycler)
        {
            if (recycler.OwnerID == 0 && !configData.canChangePublicRecyclerParams) 
                return null;
            
            if (item.info.Blueprint == null || configData.blackList.Contains(item.info.shortname))
                return true;
            
            bool flag = false;
            float num = configData.DefaultRates.Ratio;
            float percentToTake = configData.DefaultRates.percentOfMaxStackToTake;
            if (startedRecyclers.ContainsKey(recycler.net.ID))
            {
                foreach (KeyValuePair<string, ConfigData.Rates> perm in configData.PermissionsRates)
                {
                    if (permission.UserHasPermission(startedRecyclers[recycler.net.ID].ToString(), string.Format(PERMISSION_GENERIC, perm.Key)))
                    {
                        num = perm.Value.Ratio;
                        percentToTake = perm.Value.percentOfMaxStackToTake;
                        break;
                    }
                }
            }

            if (item.hasCondition)
            {
                num = Mathf.Clamp01(num * Mathf.Clamp(item.conditionNormalized * item.maxConditionNormalized, 0.1f, 1f));
            }

            int num2 = 1;
            if (item.amount > 1)
            {
                num2 = Mathf.CeilToInt(Mathf.Min((float) item.amount, (float) item.info.stackable * percentToTake));
            }

            if (item.info.Blueprint.scrapFromRecycle > 0)
            {
                float ratioScrap = configData.DefaultRates.RatioScrap;
                if (startedRecyclers.ContainsKey(recycler.net.ID))
                {
                    foreach (KeyValuePair<string, ConfigData.Rates> perm in configData.PermissionsRates)
                    {
                        if (permission.UserHasPermission(startedRecyclers[recycler.net.ID].ToString(), string.Format(PERMISSION_GENERIC, perm.Key)))
                        {
                            ratioScrap = perm.Value.RatioScrap;
                            break;
                        }
                    }
                }

                int scrap = 0;
                try
                {
                    float scrp = item.info.Blueprint.scrapFromRecycle * num2 * ratioScrap;
                    scrap = (int) (scrp);
                    if (scrp > 0f && scrp < 1f)
                    {
                        if (Random.Range(0f, 1f) < ratioScrap)
                        {
                            scrap = 1;
                            Item newItem = ItemManager.CreateByName("scrap", scrap, 0uL);
                            recycler.MoveItemToOutput(newItem);
                        }
                    }
                    else
                    {
                        Item newItem = ItemManager.CreateByName("scrap", scrap, 0uL);
                        recycler.MoveItemToOutput(newItem);
                    }
                }
                catch
                {
                    LogToFile("debug", $"[{DateTime.Now}] GOT ERROR recycler of player {recycler.OwnerID} tried to recycle {item.info.shortname}x{num2} to scrap {scrap}", this);
                }
            }

            item.UseItem(num2);
            foreach (ItemAmount ingredient in item.info.Blueprint.ingredients)
            {
                if (ingredient.itemDef.shortname != "scrap")
                {
                    float num3 = num2 * num * (float) ingredient.amount / (float) item.info.Blueprint.amountToCreate;
                    int num4 = Mathf.FloorToInt(num3);
                    if (num3 < 1f && UnityEngine.Random.Range(0f, 1f) > 0.5f) num4 = 1;
                    if (num4 > 0)
                    {
                        int num5 = Mathf.CeilToInt((float) num4 / (float) ingredient.itemDef.stackable);
                        for (int k = 0; k < num5; k++)
                        {
                            int num6 = 0;
                            try
                            {
                                num6 = (num4 <= ingredient.itemDef.stackable) ? num4 : ingredient.itemDef.stackable;
                                Item newItem2 = ItemManager.Create(ingredient.itemDef, num6, 0uL);
                                if (!recycler.MoveItemToOutput(newItem2))
                                {
                                    flag = true;
                                }
                            }
                            catch
                            {
                                LogToFile("debug", $"[{DateTime.Now}] GOT ERROR recycler of player {recycler.OwnerID} tried to recycle {item.info.shortname}x{num2} to ingredient {ingredient.itemDef.shortname}x{num6}", this);
                            }

                            num4 -= num6;
                            if (num4 <= 0)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            if (flag) recycler.StopRecycling();
            return true;
        }

        private void OnLootSpawn(LootContainer container)
        {
            timer.In(1f, () =>
            {
                if (!container || container.IsDestroyed) 
                    return;
                
                ConfigData.Loot cont;
                if (!configData.FindLootContainer(container.ShortPrefabName, out cont))
                    return;
                
                if (cont.probability < 1) 
                    return;
                
                if (Random.Range(0, 100) <= cont.probability)
                {
                    container.inventorySlots = container.inventory.itemList.Count() + 5;
                    container.inventory.capacity = container.inventory.itemList.Count() + 5;
                    container.SendNetworkUpdateImmediate();
                    TryGiveRecycler(container.inventory);
                }
            });
        }

        private object CanStackItem(Item item, Item anotherItem)
        {
            if (item.info.itemid == recyclerItemId && item.skin != anotherItem.skin) 
                return false;
            return null;
        }

        private object OnItemSplit(Item item, int split_Amount)
        {
            if (item.info.itemid == recyclerItemId && item.skin == RECYCLER_SKIN_ID)
            {
                Item byItemId = ItemManager.CreateByItemID(item.info.itemid, 1, item.skin);
                item.amount -= split_Amount;
                byItemId.amount = split_Amount;
                byItemId.name = item.name;
                item.MarkDirty();
                return byItemId;
            }

            return null;
        }

        private object CanCombineDroppedItem(DroppedItem drItem, DroppedItem anotherDrItem)
        {
            if (drItem.item.info.itemid == recyclerItemId && drItem.item.info.itemid == anotherDrItem.item.info.itemid && drItem.item.skin != anotherDrItem.item.skin) 
                return false;
            return null;
        }
        
        private void Unload()
        {
            RecyclerEntity.OnUnload();
            
            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                CuiHelper.DestroyUi(player, UI_PICKUP);
                CuiHelper.DestroyUi(player, UI_CRAFT);
                CuiHelper.DestroyUi(player, UI_HEALTH);
            }
        }
        #endregion

        #region Functions
        private void RegisterPermissions()
        {
            foreach (KeyValuePair<string, ConfigData.Rates> perm in configData.PermissionsRates)
                permission.RegisterPermission(string.Format(PERMISSION_GENERIC, perm.Key), this);

            permission.RegisterPermission(PERMISSION_CANGET, this);
            permission.RegisterPermission(PERMISSION_CANCRAFT, this);
            permission.RegisterPermission(PERMISSION_IGNORE_COOLDOWN, this);
            permission.RegisterPermission(PERMISSION_IGNORE_CRAFT_COOLDOWN, this);
        }
        
        private bool IsOnBuildingBlock(BaseEntity entity)
        {
            GroundWatch component = entity.gameObject.GetComponent<GroundWatch>();
            List<Collider> list = Facepunch.Pool.GetList<Collider>();
            
            Vis.Colliders(entity.transform.TransformPoint(component.groundPosition), component.radius, list, component.layers, QueryTriggerInteraction.Collide);
            
            foreach (Collider collider in list)
            {
                if (collider.transform.root != entity.gameObject.transform.root)
                {
                    BaseEntity baseEntity = collider.gameObject.ToBaseEntity();
                    
                    if (baseEntity && !baseEntity.IsDestroyed && baseEntity is BuildingBlock)
                    {
                        Facepunch.Pool.FreeList(ref list);
                        return true;
                    }
                }
            }

            Facepunch.Pool.FreeList(ref list);
            return false;
        }
        
        private void ApplyRecyclerSettings(BaseCombatEntity recycler, bool init = false)
        {
            if (configData.allowDamage || configData.allowRepair)
            {
                BaseCombatEntity itemToClone = GameManager.server.FindPrefab(configData.prefabToCloneDamage).GetComponent<BaseCombatEntity>();
                recycler._maxHealth = configData.health;
                
                if (!init)
                    recycler.health = recycler.MaxHealth();
                
                if (configData.allowRepair)
                {
                    recycler.repair.enabled = true;
                    recycler.repair.itemTarget = itemToClone.repair.itemTarget;
                }

                if (configData.allowDamage)
                    recycler.baseProtection = itemToClone.baseProtection;
            }
        }

        private ConfigData.Rates GetRatesForPlayer(BasePlayer player)
        {
            foreach (KeyValuePair<string, ConfigData.Rates> perm in configData.PermissionsRates)
            {
                if (permission.UserHasPermission(player.UserIDString, string.Format(PERMISSION_GENERIC, perm.Key)))
                    return perm.Value;
            }

            return configData.DefaultRates;
        }

        private double CurrentTimeStamp() => DateTime.UtcNow.Subtract(Epoch).TotalSeconds;
        
        private float GetCraftLimit(BasePlayer player) => GetRatesForPlayer(player).craftLimit;

        private float GetSpawnLimit(BasePlayer player) => GetRatesForPlayer(player).spawnLimit;

        private float GetCraftCooldown(BasePlayer player) => GetRatesForPlayer(player).craftCooldown;

        private float GetSpawnCooldown(BasePlayer player) => GetRatesForPlayer(player).spawnCooldown;
        
        private void EndCrafting(BasePlayer player)
        {
            string message = string.Empty;
            bool hasEnoughResources = true;
            
            foreach (KeyValuePair<int, KeyValuePair<string, int>> item in itemsNeededToCraft)
            {
                if (player.inventory.GetAmount(item.Key) >= item.Value.Value) 
                    continue;
                
                message += string.Format(Message("not enough ingredient", player) + "\n", item.Value.Key, item.Value.Value);
                hasEnoughResources = false;
            }

            if (!hasEnoughResources)
            {
                SendReply(player, message);
                return;
            }

            if (configData.useCraftCooldown)
            {
                float craftCooldown = GetCraftCooldown(player);
                pluginData.userCooldownsCraft[player.userID] = CurrentTimeStamp() + craftCooldown;
            }

            if (configData.useCraftLimit)
            {
                if (!pluginData.userCrafted.ContainsKey(player.userID)) 
                    pluginData.userCrafted.Add(player.userID, 0);
                
                pluginData.userCrafted[player.userID]++;
            }

            foreach (KeyValuePair<int, KeyValuePair<string, int>> item in itemsNeededToCraft)
                player.inventory.Take(null, item.Key, item.Value.Value);
            
            SendMsg(player, GiveRecycler(player) ? "recycler crafted" : "inventory full");
        }

        private Item CreateRecycler()
        {
            Item item = ItemManager.CreateByName(configData.recyclerItemName, 1, RECYCLER_SKIN_ID);
            item.name = "Recycler";
            return item;
        }
        
        private void TryGiveRecycler(ItemContainer container)
        {
            Item item = CreateRecycler();
            
            if (!item.MoveToContainer(container, -1, false))
                item.Remove(0f);
        }

        private bool GiveRecycler(BasePlayer player)
        {
            Item item = CreateRecycler();
            
            if (!player.inventory.GiveItem(item))
            {
                item.Drop(player.inventory.containerMain.dropPosition, player.inventory.containerMain.dropVelocity);
                return false;
            }
            
            if (!string.IsNullOrEmpty(item.name))
                player.Command("note.inv", item.info.itemid, 1, item.name, (int) BaseEntity.GiveItemReason.PickedUp);
            else player.Command("note.inv", item.info.itemid, 1, string.Empty, (int) BaseEntity.GiveItemReason.PickedUp);

            return true;
        }
        #endregion

        #region Commands
        private void cmdRec(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_CANGET))
            {
                SendMsg(player, "badCommand");
                return;
            }

            if (configData.useSpawnCooldown)
            {
                if (!permission.UserHasPermission(player.UserIDString, PERMISSION_IGNORE_COOLDOWN))
                {
                    double time = CurrentTimeStamp();
                    float spawnCooldown = GetSpawnCooldown(player);
                    
                    if (!pluginData.userCooldowns.ContainsKey(player.userID)) 
                        pluginData.userCooldowns.Add(player.userID, time + spawnCooldown);
                    else
                    {
                        double nextUseTime = pluginData.userCooldowns[player.userID];
                        if (nextUseTime > time)
                        {
                            SendMsg(player, "cooldown", true, (int) (nextUseTime - time));
                            return;
                        }
                        
                        pluginData.userCooldowns[player.userID] = time + spawnCooldown;
                    }
                }
            }

            if (configData.useSpawnLimit)
            {
                if (!pluginData.userSpawned.ContainsKey(player.userID)) 
                    pluginData.userSpawned.Add(player.userID, 0);
                
                float spawnLimit = GetSpawnLimit(player);
                if (pluginData.userSpawned[player.userID] >= spawnLimit)
                {
                    SendMsg(player, "limit", true, spawnLimit);
                    return;
                }

                pluginData.userSpawned[player.userID]++;
            }

            SendMsg(player, GiveRecycler(player) ? "recycler got" : "inventory full");
        }

        private void cmdCraft(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_CANCRAFT))
            {
                SendMsg(player, "cannot craft");
                return;
            }

            if (configData.useCraftCooldown)
            {
                if (!permission.UserHasPermission(player.UserIDString, PERMISSION_IGNORE_CRAFT_COOLDOWN))
                {
                    double time = CurrentTimeStamp();
                    if (pluginData.userCooldownsCraft.ContainsKey(player.userID))
                    {
                        double nextUseTime = pluginData.userCooldownsCraft[player.userID];
                        if (nextUseTime > time)
                        {
                            SendMsg(player, "cooldown craft", true, (int)(nextUseTime - time));
                            return;
                        }
                    }
                }
            }

            if (configData.useCraftLimit)
            {
                if (!pluginData.userCrafted.ContainsKey(player.userID)) 
                    pluginData.userCrafted.Add(player.userID, 0);
                
                float craftLimit = GetCraftLimit(player);
                if (pluginData.userCrafted[player.userID] >= craftLimit)
                {
                    SendMsg(player, "limit", true, craftLimit);
                    return;
                }
            }

            if (configData.useUIForCrafting)
            {
                ShowUICraft(player);
                return;
            }

            EndCrafting(player);
        }
        #endregion

        #region Console Commands
        [ConsoleCommand("craftrecycler")]
        private void CcmdCraft(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null)
                return;
            
            CuiHelper.DestroyUi(player, UI_CRAFT);

            if (arg.Args == null)
            {
                if (!permission.UserHasPermission(player.UserIDString, PERMISSION_CANCRAFT))
                {
                    SendMsg(player, "cannot craft");
                    return;
                }

                EndCrafting(player);
            }
        }

        [ConsoleCommand("giverecycler")]
        private void cmdGiveRecycler(ConsoleSystem.Arg arg)
        {
            if (arg.Connection != null)
            {
                BasePlayer player = arg.Connection.player as BasePlayer;
                if (player == null)
                    return;

                if (player.net.connection.authLevel < 2)
                    return;
            }

            if (arg.Args == null || arg.Args.Length < 1)
            {
                SendReply(arg, "bad syntax");
                return;
            }

            BasePlayer targetPlayer = BasePlayer.Find(arg.Args[0]);
            if (targetPlayer == null)
            {
                SendReply(arg, "error player not found for give");
                return;
            }

            SendReply(targetPlayer, Message(GiveRecycler(targetPlayer) ? "recycler got" : "inventory full", targetPlayer));
        }
        
        [ConsoleCommand("pickuprecycler")]
        private void cmdPickupRecycler(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Connection.player as BasePlayer;
            if (player == null)
                return;
            
            CuiHelper.DestroyUi(player, UI_PICKUP);

            if (arg.Args != null)
                return;
            
            if (!pickupRecyclers.ContainsKey(player)) 
                return;

            RecyclerEntity recyclerEntity;
            if (!pickupRecyclers.TryGetValue(player, out recyclerEntity))
                return;
            
            pickupRecyclers.Remove(player);

            Recycler recycler = recyclerEntity.Recycler;
            
            if (recycler && !recycler.IsDestroyed)
            {
                recycler.inventory.Drop("assets/prefabs/misc/item drop/item_drop.prefab", recycler.transform.position + new Vector3(0f, 1f, 0f), recycler.transform.rotation);

                recycler.Kill();
                
                SendMsg(player, GiveRecycler(player) ? "recycler got" : "inventory full");
            }
        }
        #endregion
        
         #region UI Helper
        public static class UI
        {
            private const string COLOR_CLEAR = "0 0 0 0";

            public static CuiElementContainer Container(string panel, Anchor anchor, Offset offset)
            {
                CuiElementContainer container = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = { Color = COLOR_CLEAR },
                            RectTransform = { AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString() },
                            CursorEnabled = false
                        },
                        new CuiElement().Parent = "Hud",
                        panel
                    }
                };
                return container;
            }

            public static CuiElementContainer Container(string panel, string color, Anchor anchor, Offset offset)
            {
                CuiElementContainer container = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = { Color = color, Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat" },
                            RectTransform = { AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString() },
                            CursorEnabled = true
                        },
                        new CuiElement().Parent = "Hud",
                        panel
                    }
                };
                return container;
            }

            public static CuiElement Panel(CuiElementContainer container, string panel, string color, Anchor anchor, Offset offset)
            {
                CuiElement cuiElement;
                container.Add(cuiElement = new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiImageComponent {Color = color, Sprite = "assets/content/ui/ui.background.tile.psd", Material = "assets/icons/iconmaterial.mat"},
                        new CuiRectTransformComponent {AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString()},
                    }
                });
                return cuiElement;
            }

            public static void Label(CuiElementContainer container, string panel, string text, int size, Anchor anchor, Offset offset, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiTextComponent { FontSize = size, Align = align, Text = text },
                        new CuiRectTransformComponent {AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString()},
                    }
                });
            }

            public static void Image(CuiElementContainer container, string panel, int itemId, ulong skinId, Anchor anchor, Offset offset)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiImageComponent { ItemId = itemId, SkinId = skinId },
                        new CuiRectTransformComponent { AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString() },
                    }
                });
            }

            public static void Button(CuiElementContainer container, string panel, string color, string text, int fontSize, Anchor anchor, Offset offset, string command)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiImageComponent { Color = color, Sprite = "assets/content/ui/ui.background.tile.psd", Material = "assets/icons/iconmaterial.mat" },
                        new CuiRectTransformComponent {AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString()},
                    }
                });
                
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiRectTransformComponent { AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString() },
                        new CuiTextComponent {Text = text, FontSize = fontSize, Align = TextAnchor.MiddleCenter}
                    }
                });
                
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiButtonComponent {Color = COLOR_CLEAR, Command = command},
                        new CuiRectTransformComponent { AnchorMin = anchor.Min.ToString(), AnchorMax = anchor.Max.ToString(), OffsetMin = offset.Min.ToString(), OffsetMax = offset.Max.ToString() },
                    }
                });
            }

            public struct Anchor
            {
                public Bounds Min;
                public Bounds Max;

                public Anchor(float xMin, float yMin, float xMax, float yMax)
                {
                    this.Min = new Bounds(xMin, yMin);
                    this.Max = new Bounds(xMax, yMax);
                }
                
                public static Anchor TopLeft = new Anchor(0f, 1f, 0f, 1f);
                public static Anchor TopCenter = new Anchor(0.5f, 1f, 0.5f, 1f);
                public static Anchor TopRight = new Anchor(1f, 1f, 1f, 1f);
                public static Anchor CenterLeft = new Anchor(0f, 0.5f, 0f, 0.5f);
                public static Anchor Center = new Anchor(0.5f, 0.5f, 0.5f, 0.5f);
                public static Anchor CenterRight = new Anchor(1f, 0.5f, 1f, 0.5f);
                public static Anchor BottomLeft = new Anchor(0f, 0f, 0f, 0f);
                public static Anchor BottomCenter = new Anchor(0.5f, 0f, 0.5f, 0f);
                public static Anchor BottomRight = new Anchor(1f, 0f, 1f, 0f);

                public static Anchor FullStretch = new Anchor(0f, 0f, 1f, 1f);
                public static Anchor TopStretch = new Anchor(0f, 1f, 1f, 1f);
                public static Anchor HoriztonalCenterStretch = new Anchor(0f, 0.5f, 1f, 0.5f);
                public static Anchor BottomStretch = new Anchor(0f, 0f, 1f, 0f);
                public static Anchor LeftStretch = new Anchor(0f, 0f, 0f, 1f);
                public static Anchor VerticalCenterStretch = new Anchor(0.5f, 0f, 0.5f, 1f);
                public static Anchor RightStretch = new Anchor(1f, 0f, 1f, 1f);

                public override string ToString() => $"{Min.ToString()} {Max.ToString()}";
            }

            public struct Offset
            {
                public Bounds Min;
                public Bounds Max;

                public static Offset zero = new Offset(0, 0, 0, 0);

                public Offset(float xMin, float yMin, float xMax, float yMax)
                {
                    this.Min = new Bounds(xMin, yMin);
                    this.Max = new Bounds(xMax, yMax);
                }
                
                public override string ToString() => $"{Min.ToString()} {Max.ToString()}";
            }

            public struct Bounds
            {
                public readonly float X;
                public readonly float Y;

                public Bounds(float x, float y)
                {
                    this.X = x;
                    this.Y = y;
                }

                public override string ToString() => $"{X} {Y}";
            }
        }
        #endregion

        #region UI
        private const string UI_CRAFT = "homerecycler.craft";
        private const string UI_PICKUP = "homerecycler.pickup";
        private const string UI_HEALTH = "homerecycler.health";
        
        private const string RED = "#CE422B";
        private const string GREEN = "#BAFF00";

        private readonly Hash<BasePlayer, Timer> m_HealthTimers = new Hash<BasePlayer, Timer>();
        
        private void ShowUIHealth(BasePlayer player, string message)
        {
            CuiElementContainer container = UI.Container(UI_HEALTH, UI.Anchor.Center, new UI.Offset(-125, -125, 125, 100));
            UI.Label(container, UI_HEALTH, message, 14, UI.Anchor.FullStretch, UI.Offset.zero);
            
            CuiHelper.DestroyUi(player, UI_HEALTH);
            CuiHelper.AddUi(player, container);

            Timer t;
            if (m_HealthTimers.TryGetValue(player, out t))
                t.Destroy();

            m_HealthTimers[player] = timer.In(3f, () =>
            {
                CuiHelper.DestroyUi(player, UI_HEALTH);
                m_HealthTimers.Remove(player);
            });
        }

        private void ShowUICraft(BasePlayer player)
        {            
            const int ITEM_PIXELS = 68;

            float height = (float)((configData.itemsNeededToCraft.Count * ITEM_PIXELS) + 50) * 0.5f;

            CuiElementContainer container = UI.Container(UI_CRAFT, "0 0 0 0.9", UI.Anchor.Center, new UI.Offset(-125, -height, 125, height));

            UI.Label(container, UI_CRAFT, Message("CraftTitle", player), 16, UI.Anchor.TopStretch, new UI.Offset(0, -25, 0, 0));

            bool hasEnoughResources = true;

            int i = 0;
            foreach (KeyValuePair<string, int> cost in configData.itemsNeededToCraft)
            {
                ItemDefinition itemDefinition;
                if (ItemManager.itemDictionaryByName.TryGetValue(cost.Key, out itemDefinition))
                {
                    CuiElement parent = UI.Panel(container, UI_CRAFT, "0 0 0 0", UI.Anchor.TopStretch, new UI.Offset(2, -25 - (ITEM_PIXELS * (i + 1)), -2, -25 - (ITEM_PIXELS * i)));
                    UI.Panel(container, parent.Name, "1 1 1 0.1", UI.Anchor.FullStretch, new UI.Offset(0, 1, 0, -1));
                    UI.Image(container, parent.Name, itemDefinition.itemid, 0UL, UI.Anchor.CenterLeft, new UI.Offset(2, -32, 66, 32));
                    UI.Label(container, parent.Name, itemDefinition.displayName.english, 12, UI.Anchor.TopStretch, new UI.Offset(70, -22.66667f, 0, 0), TextAnchor.MiddleLeft);
                    UI.Label(container, parent.Name, string.Format(Message("Required", player), cost.Value), 12, UI.Anchor.HoriztonalCenterStretch, new UI.Offset(70, -11.33333f, 0, 11.33333f), TextAnchor.MiddleLeft);

                    int playerAmount = player.inventory.GetAmount(itemDefinition.itemid);
                    string have;
                    if (playerAmount < cost.Value)
                    {
                        hasEnoughResources = false;
                        have = string.Format(Message("Have", player), RED, playerAmount);
                    }
                    else have = string.Format(Message("Have", player), GREEN, playerAmount);

                    UI.Label(container, parent.Name, have, 12, UI.Anchor.BottomStretch, new UI.Offset(70, 0f, 0, 22.66667f), TextAnchor.MiddleLeft);
                }

                i++;
            }

            CuiElement buttonContainer = UI.Panel(container, UI_CRAFT, "0 0 0 0", UI.Anchor.BottomStretch, new UI.Offset(0, 0, 0, 25));
            UI.Button(container, buttonContainer.Name, "0.8078 0.2588 0.1686 0.8", Message("Cancel", player), 14, UI.Anchor.FullStretch, new UI.Offset(2, 2, -150, -2), "craftrecycler close");

            if (hasEnoughResources)
                UI.Button(container, buttonContainer.Name, "0.7292 1 0 0.8", Message("Craft", player), 14, UI.Anchor.FullStretch, new UI.Offset(102, 2, -2, -2), "craftrecycler");
            else UI.Button(container, buttonContainer.Name, "0.9622 0.9022 0.5129 0.8", Message("InsuffRes", player), 14, UI.Anchor.FullStretch, new UI.Offset(102, 2, -2, -2), string.Empty);

            CuiHelper.DestroyUi(player, UI_CRAFT);
            CuiHelper.AddUi(player, container);
        }

        private void ShowUIPickup(BasePlayer player)
        {
            CuiElementContainer container = UI.Container(UI_PICKUP, "0 0 0 0.9", UI.Anchor.Center, new UI.Offset(-125, -25, 125, 25));

            UI.Label(container, UI_PICKUP, Message("UIPickup", player), 16, UI.Anchor.TopStretch, new UI.Offset(0, -25, 0, 0));

            CuiElement buttonContainer = UI.Panel(container, UI_PICKUP, "0 0 0 0", UI.Anchor.BottomStretch, new UI.Offset(0, 0, 0, 25));
            UI.Button(container, buttonContainer.Name, "0.8078 0.2588 0.1686 0.8", Message("UIPickupNo", player), 14, UI.Anchor.FullStretch, new UI.Offset(2, 2, -126, -2), "pickuprecycler close");

            UI.Button(container, buttonContainer.Name, "0.7292 1 0 0.8", Message("UIPickupYes", player), 14, UI.Anchor.FullStretch, new UI.Offset(126, 2, -2, -2), "pickuprecycler");
            
            CuiHelper.DestroyUi(player, UI_PICKUP);
            CuiHelper.AddUi(player, container);
        }
        #endregion
        
        #region Component
        private class RecyclerEntity : MonoBehaviour
        {
            private Recycler m_Entity;

            public Recycler Recycler => m_Entity;
            
            public ulong OwnerID => m_Entity ? m_Entity.OwnerID : 0UL;

            private static readonly List<RecyclerEntity> m_AllRecyclers = new List<RecyclerEntity>();

            private void Awake()
            {
                m_Entity = GetComponent<Recycler>();
                
                AddComponentIfMissing<DestroyOnGroundMissing>();
                AddComponentIfMissing<GroundWatch>();
                
                m_AllRecyclers.Add(this);
            }

            private void OnDestroy() =>  m_AllRecyclers.Remove(this);

            private void AddComponentIfMissing<T>() where T : Component
            {
                if (!gameObject.GetComponent<T>())
                    gameObject.AddComponent<T>();
            }

            public static void OnUnload()
            {
                for (int i = m_AllRecyclers.Count - 1; i >= 0; i--)
                {
                    RecyclerEntity recyclerEntity = m_AllRecyclers[i];
                    if (recyclerEntity)
                        Destroy(recyclerEntity);
                }
                
                m_AllRecyclers.Clear();
            }
        }
        #endregion

        #region Config        
        private ConfigData configData;
        private class ConfigData
        {      
            public string chatCommand { get; set; }
            public string craftCommand { get; set; }
            public bool useUIForCrafting { get; set; }
            public string recyclerItemName { get; set; }
            public string recyclerShortPrefabName { get; set; }
            public bool allowDamage { get; set; }
            public bool allowRepair { get; set; }
            public string prefabToCloneDamage { get; set; }
            public float health { get; set; }
            public bool canChangePublicRecyclerParams { get; set; }
            public bool restrictUseByCupboard { get; set; }
            public bool adminSpawnsPublicRecycler { get; set; }
            public bool useSpawning { get; set; }
            public bool useCrafting { get; set; }
            public bool useSpawnCooldown { get; set; }
            public bool useCraftCooldown { get; set; }
            public bool useSpawnLimit { get; set; }
            public bool useCraftLimit { get; set; }
            public bool allowDeployOnGround { get; set; }
            public bo
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху