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

FREE PersonalRecycler : 1.0.11 1.0.11

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

/* Update 1.0.11
 * Fixed an issue with recycler's not being deployable when the max was 0.*/

namespace Oxide.Plugins
{
    [Info("PersonalRecycler", "imthenewguy", "1.0.11")]
    [Description("Personal recycler")]
    class PersonalRecycler : RustPlugin
    {

        #region Config

        private Configuration config;
        public class Configuration
        {
            [JsonProperty("How many recyclers would you like players with permissions to start with?")]
            public int start_recyclers = 1;

            [JsonProperty("Maximum recyclers that a player can deploy [0 = no limit]")]
            public int max_deployed = 0;

            [JsonProperty("Permission based overrides for maximum recyclers [perm | amount]")]
            public Dictionary<string, int> max_override = new Dictionary<string, int>();

            [JsonProperty("Only allow the player who deployed the recycler to access it?")]
            public bool restrict_usage = true;

            [JsonProperty("Allow team mates to access each others recyclers?")]
            public bool allow_team = false;

            [JsonProperty("Allow for recycler credits to carry over across a map wipe?")]
            public bool recycler_credits_persist = true;

            [JsonProperty("Recycler pickup options")]
            public PickupOptions pickup_options = new PickupOptions();

            [JsonProperty("Damage caused to the item when picked up?")]
            public float pickup_damage = 20;

            [JsonProperty("Item starting health")]
            public float start_health = 100;

            [JsonProperty("Destroy the recycler if it's parented ground entity is removed?")]
            public bool use_ground_watch = true;

            [JsonProperty("How often should ground watch check to see if a recycler is floating? (seconds)")]
            public float ground_watch_check_delay = 3f;

            [JsonProperty("Require the player to be holding a hammer when using the crecycler command?")]
            public bool require_hammer_command = false;

            [JsonProperty("Play an effect when a recycler redemption is added to a player via console?")]
            public bool credit_sound = true;

            [JsonProperty("Recycler efficiency")]
            public float efficiency = 0.6f;

            public string ToJson() => JsonConvert.SerializeObject(this);

            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }

        public class PickupOptions 
        {
            [JsonProperty("Allow players to pickup their recyclers?")]
            public bool allow_pickup = true;

            [JsonProperty("Allow players to pickup their recyclers by hitting it with a hammer?")]
            public bool hammer_hit = true;

            [JsonProperty("Allow players to pickup their recyclers by targeting it with a hammer and pressing fire_3?")]
            public bool mouse_3 = true;
        }
        

        protected override void LoadDefaultConfig() => config = new Configuration();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    throw new JsonException();
                }

                if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys))
                {
                    PrintToConsole("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch
            {
                PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig()
        {
            PrintToConsole($"Configuration changes saved to {Name}.json");
            Config.WriteObject(config, true);
        }

        #endregion

        #region Const

        const ulong recycler_skin = 2531319393;
        const string recycler_short = "box.wooden.large";
        const string recycler_name = "Recycler";

        #endregion

        #region Data

        PCDATA pcdData;
        private DynamicConfigFile PCDDATA;

        void Init()
        {
            permission.RegisterPermission("personalrecycler.place", this);
            permission.RegisterPermission("personalrecycler.use", this);
            permission.RegisterPermission("personalrecycler.admin", this);
            PCDDATA = Interface.Oxide.DataFileSystem.GetFile("PersonalRecycler");            

            if (!config.pickup_options.allow_pickup)
            {
                Unsubscribe("OnHammerHit");
                Unsubscribe("OnPlayerInput");
            }
            else if (!config.pickup_options.hammer_hit) Unsubscribe("OnHammerHit");
            else if (!config.pickup_options.mouse_3) Unsubscribe("OnPlayerInput");
        }

        void Unload()
        {
            SaveData();
            foreach (var recycler in BaseEntity.serverEntities.OfType<Recycler>())
            {
                DestroyGroundWatch(recycler);
            }
        }

        void Loaded()
        {
            LoadData();
        }

        void SaveData()
        {
            PCDDATA.WriteObject(pcdData);
        }

        void LoadData()
        {
            try
            {
                pcdData = Interface.GetMod().DataFileSystem.ReadObject<PCDATA>("PersonalRecycler");
            }
            catch
            {
                Puts("Couldn't load player data, creating new Playerfile");
                pcdData = new PCDATA();
            }
        }
        class PCDATA
        {
            public Dictionary<ulong, PlayerInfo> pentity = new Dictionary<ulong, PlayerInfo>();
            public Dictionary<ulong, RecyclersInfo> private_recyclers = new Dictionary<ulong, RecyclersInfo>();
        }

        public class RecyclersInfo
        {
            public ulong playerid;
            public float condition;
            public bool groundWatch;
            public RecyclersInfo(ulong playerid, float condition, bool groundWatch)
            {
                this.playerid = playerid;
                this.condition = condition;
                this.groundWatch = groundWatch;
            }
        }

        public class PlayerInfo
        {
            public string name;
            public int available_recyclers;
            public List<ulong> recycler_ids = new List<ulong>();
            public PlayerInfo(string name)
            {
                this.name = name;
            }

            public List<float> stored_recyclers = new List<float>();
        }

        #endregion

        #region localization

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["decreaserecyclers_success"] = "Removed 1 recycler from each player.",
                ["NoRecyclers"] = "You have no recyclers to redeem.",
                ["RecyclersLeft"] = "You have {0} recyclers left to redeem.Type /redeemrecycler to redeem one into your inventory.",
                ["NoPerms"] = "You do not have permission to access this command.",
                ["RecyclerRedeemed"] = "Redeemed recycler.You have {0} recyclers remaining.",
                ["Addrecycler_usage"] = "Usage: /addrecycler <player name>",
                ["AddedRecycler_success"] = "Added a recycler for {0}",
                ["AddedRecycler_received"] = "You were given a recycler by {0}.Redeemable: {1}",
                ["Clearrecyclers_usage"] = "Usage: /clearrecyclers <name>",
                ["Clearrecyclers_nodata"] = "No data found for {0}",
                ["Clearrecyclers_success"] = "Cleared all recycler data for {0}",
                ["clearrecyclerdata_success"] = "Cleared all recycler data.",
                ["crecycler_NotEmpty"] = "You cannot pickup your recycler with items inside of it.Empty it first.",
                ["crecycler_Notyours"] = "You cannot pickup this recycler!",
                ["CannotLoot"] = "You cannot loot someones personal recycler.",
                ["RecyclerBroken"] = "Your recycler has broken!",
                ["FindPlayerByName_TooMany"] = "More than one player found: {0}",
                ["FindPlayerByName_NoMatch"] = "No player was found that matched: {0}",
                ["ConsoleRedeemed"] = "You redeemed a Recycler token.Your new recycler balance is {0}",
                ["MaxReached"] = "You have already reached the maximum amount of recyclers that can be deployed: {0}",
                ["NoPermsPlace"] = "You do not have permission to place this recycler.",
                ["SkinboxReturn"] = "You cannot skin this item/entity with the recycler skin.",
            }, this);
        }

        #endregion

        #region Chat Command

        [ChatCommand("decreaserecyclers")]
        void DecreaseRecyclers(BasePlayer player)
        {
            if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.admin")) return;
            foreach (KeyValuePair<ulong, PlayerInfo> kvp in pcdData.pentity)
            {
                if (kvp.Value.available_recyclers > 1)
                {
                    kvp.Value.available_recyclers--;
                    if (kvp.Value.available_recyclers < 0) kvp.Value.available_recyclers = 0;
                }
            }
            PrintToChat(player, lang.GetMessage("decreaserecyclers_success", this, player.UserIDString));
        }

        [ChatCommand("recyclers")]
        void RecyclerBalance(BasePlayer player)
        {
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(player.userID, out pi))
            {
                if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.use"))
                {
                    PrintToChat(player, lang.GetMessage("NoRecyclers", this, player.UserIDString));
                    return;
                }
                else
                {
                    pcdData.pentity.Add(player.userID, pi = new PlayerInfo(player.displayName));
                    pi.name = player.displayName;
                    pi.available_recyclers = config.start_recyclers;
                    PrintToChat(player, string.Format(lang.GetMessage("RecyclersLeft", this, player.UserIDString), pi.available_recyclers));
                    return;
                }
            }
            if (pi.available_recyclers <= 0) PrintToChat(player, lang.GetMessage("NoRecyclers", this, player.UserIDString));
            else PrintToChat(player, string.Format(lang.GetMessage("RecyclersLeft", this, player.UserIDString), pi.available_recyclers));
        }

        const string perm_use = "personalrecycler.use";
        const string perm_admin = "personalrecycler.admin";

        [ChatCommand("redeemrecycler")]
        void HandleRecyclerRedemption(BasePlayer player)
        {
            PlayerInfo pi;

            bool isAdmin = permission.UserHasPermission(player.UserIDString, perm_admin);

            if (!permission.UserHasPermission(player.UserIDString, perm_use) && !isAdmin)
            {
                if (pcdData.pentity.TryGetValue(player.userID, out pi) && pi.available_recyclers <= 0)
                {
                    PrintToChat(player, lang.GetMessage("NoRecyclers", this, player.UserIDString));
                    return;
                }
            }
            else
            {
                if (pcdData.pentity.TryGetValue(player.userID, out pi))
                {
                    if (pi.available_recyclers <= 0 && !isAdmin)
                    {
                        PrintToChat(player, lang.GetMessage("NoRecyclers", this, player.UserIDString));
                        return;
                    }
                }
                else
                {
                    pcdData.pentity.Add(player.userID, pi = new PlayerInfo(player.displayName));
                    pi.available_recyclers = config.start_recyclers;
                }
            }

            if (pi == null)
            {
                PrintToChat(player, "Something went wrong.");
                return;
            }

            if (!isAdmin) pi.available_recyclers--;
            if (pi.available_recyclers < 0) pi.available_recyclers = 0;
            SpawnRecycler(player);
            PrintToChat(player, string.Format(lang.GetMessage("RecyclerRedeemed", this, player.UserIDString), pi.available_recyclers));
        }

        [ChatCommand("addrecycler")]
        void AddRecycler(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.admin")) return;
            if (args.Length != 1)
            {
                PrintToChat(player, lang.GetMessage("Addrecycler_usage", this, player.UserIDString));
                return;
            }
            var target = FindPlayerByName(args[0]);
            if (target == null) return;
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(target.userID, out pi))
            {
                pcdData.pentity.Add(target.userID, pi = new PlayerInfo(player.displayName));
                pi.name = target.displayName;
            }
            pi.available_recyclers++;
            PrintToChat(player, string.Format(lang.GetMessage("AddedRecycler_success", this, player.UserIDString), target.displayName));
            PrintToChat(player, string.Format(lang.GetMessage("AddedRecycler_received", this, player.UserIDString), player.displayName, pi.available_recyclers));
        }

        [ChatCommand("clearrecyclers")]
        void ClearData(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.admin")) return;
            if (args.Length != 1)
            {
                PrintToChat(player, lang.GetMessage("Clearrecyclers_usage", this, player.UserIDString));
                return;
            }
            var target = FindPlayerByName(args[0]);
            if (target == null) return;
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(target.userID, out pi))
            {
                PrintToChat(player, string.Format(lang.GetMessage("Clearrecyclers_nodata", this, player.UserIDString), target.displayName));
                return;
            }
            foreach (var id in pi.recycler_ids)
            {
                if (pcdData.private_recyclers.ContainsKey(id)) pcdData.private_recyclers.Remove(id);
            }
            pi.recycler_ids.Clear();
            PrintToChat(player, string.Format(lang.GetMessage("Clearrecyclers_success", this, player.UserIDString), target.displayName));
        }

        [ChatCommand("clearrecyclerdata")]
        void ClearRecyclerData(BasePlayer player)
        {
            if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.admin")) return;
            foreach (KeyValuePair<ulong, PlayerInfo> kvp in pcdData.pentity)
            {
                kvp.Value.recycler_ids.Clear();
            }
            pcdData.private_recyclers.Clear();
            PrintToChat(player, lang.GetMessage("clearrecyclerdata_success", this, player.UserIDString));
        }

        [ChatCommand("crecycler")]
        void CollectRecycler(BasePlayer player)
        {
            var recycler = GetTargetEntity(player) as Recycler;
            if (recycler == null || recycler.OwnerID == 0)
            {
                var nearbyRecyclers = FindEntitiesOfType<Recycler>(player.transform.position, 10f);
                foreach (var rec in nearbyRecyclers)
                {
                    if (rec.OwnerID == player.userID)
                    {
                        recycler = rec;
                        break;
                    }
                }
                Pool.FreeList(ref nearbyRecyclers);
                if (recycler == null || recycler.OwnerID == 0)
                {
                    var parent = player.GetParentEntity();
                    if (parent != null && parent.ShortPrefabName == "tugboat")
                    {
                        foreach (var child in parent.children)
                        {
                            if (child is Recycler && child.OwnerID == player.userID)
                            {
                                recycler = child as Recycler;
                                break;
                            }
                        }
                    }
                    if (recycler == null || recycler.OwnerID == 0) return;
                }
            }
            var tool = player.GetActiveItem();
            if (config.require_hammer_command && tool?.info.shortname != "toolgun" && tool?.info.shortname != "hammer")
            {
                return;
            }

            if (recycler.inventory.itemList != null && recycler.inventory.itemList.Count > 0)
            {
                PrintToChat(player, lang.GetMessage("crecycler_NotEmpty", this, player.UserIDString));
                return;
            }

            if (player.userID != recycler.OwnerID && (!config.allow_team || !player.Team.members.Contains(recycler.OwnerID)))
            {
                PrintToChat(player, lang.GetMessage("crecycler_Notyours", this, player.UserIDString));
                return;
            }

            PickupRecycler(player, recycler);            
        }

        private static List<T> FindEntitiesOfType<T>(Vector3 pos, float radius, int m = -1) where T : BaseEntity
        {
            int hits = Physics.OverlapSphereNonAlloc(pos, radius, Vis.colBuffer, m, QueryTriggerInteraction.Collide);
            List<T> entities = Pool.GetList<T>();
            for (int i = 0; i < hits; i++)
            {
                var entity = Vis.colBuffer[i]?.ToBaseEntity();
                if (entity is T) entities.Add(entity as T);
                Vis.colBuffer[i] = null;
            }
            return entities;
        }



        #endregion

        #region Hooks

        object OnHammerHit(BasePlayer player, HitInfo info)
        {
            var recycler = info?.HitEntity as Recycler;
            if (recycler == null || recycler.OwnerID == 0) return null;

            if (recycler.inventory.itemList != null && recycler.inventory.itemList.Count > 0)
            {
                PrintToChat(player, lang.GetMessage("crecycler_NotEmpty", this, player.UserIDString));
                return null;
            }

            if (player.userID != recycler.OwnerID && (!config.allow_team || player.Team == null || player.Team.members == null || !player.Team.members.Contains(recycler.OwnerID)))
            {
                PrintToChat(player, lang.GetMessage("crecycler_Notyours", this, player.UserIDString));
                return null;
            }

            PickupRecycler(player, recycler);

            return null;
        }

        void PickupRecycler(BasePlayer player, Recycler recycler)
        {
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(player.userID, out pi)) pcdData.pentity.Add(player.userID, pi = new PlayerInfo(player.displayName));

            RecyclersInfo ri;
            pcdData.private_recyclers.TryGetValue(recycler.net.ID.Value, out ri);            

            pi.recycler_ids.Remove(recycler.net.ID.Value);
            SpawnRecycler(player, ri != null ? ri.condition - config.pickup_damage : config.start_health - config.pickup_damage);

            pcdData.private_recyclers.Remove(recycler.net.ID.Value);

            recycler.StopRecycling();
            Unsubscribe("OnEntityKill");
            recycler.KillMessage();
            Subscribe("OnEntityKill");
        }

        void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!input.WasJustReleased(BUTTON.FIRE_THIRD) || player == null || player.GetActiveItem() == null) return;
            var recycler = GetTargetEntity(player) as Recycler;
            if (recycler == null || recycler.OwnerID == 0) return;
            var tool = player.GetActiveItem();
            if (tool.info.shortname != "toolgun" && tool.info.shortname != "hammer") return;

            if (recycler.inventory.itemList != null && recycler.inventory.itemList.Count > 0)
            {
                PrintToChat(player, lang.GetMessage("crecycler_NotEmpty", this, player.UserIDString));
                return;
            }

            if (player.userID != recycler.OwnerID && (!config.allow_team || !player.Team.members.Contains(recycler.OwnerID)))
            {
                PrintToChat(player, lang.GetMessage("crecycler_Notyours", this, player.UserIDString));
                return;
            }

            PickupRecycler(player, recycler);            
        }

        void OnEntityKill(Recycler entity)
        {
            if (entity == null || entity.OwnerID == 0) return;
            foreach (var pi in pcdData.pentity)
            {
                if (pi.Value.recycler_ids.Contains(entity.net.ID.Value))
                {
                    List<Item> items = Pool.GetList<Item>();
                    items.AddRange(entity.inventory?.itemList);
                    foreach (var _item in items)
                    {
                        _item.DropAndTossUpwards(entity.transform.position, UnityEngine.Random.Range(1f, 3f));
                    }
                    Pool.FreeList(ref items);
                    RecyclersInfo ri;
                    if (pcdData.private_recyclers.TryGetValue(entity.net.ID.Value, out ri) && ri.condition - config.pickup_damage > 0)
                    {
                        var item = ItemManager.CreateByName(recycler_short, 1, recycler_skin);
                        item.name = recycler_name;
                        var condition = ri.condition - config.pickup_damage;
                        item.maxCondition = condition;
                        item.DropAndTossUpwards(entity.transform.position);
                        pcdData.private_recyclers.Remove(entity.net.ID.Value);
                    }

                    pi.Value.recycler_ids.Remove(entity.net.ID.Value);
                    break;
                }
            }

            pcdData.private_recyclers.Remove(entity.net.ID.Value);
        }

        void OnServerSave()
        {
            SaveData();
        }

        void OnNewSave(string filename)
        {
            List<ulong> delete_users = new List<ulong>();
            foreach (KeyValuePair<ulong, PlayerInfo> kvp in pcdData.pentity)
            {
                kvp.Value.recycler_ids.Clear();
                if (permission.UserHasPermission(kvp.Key.ToString(), "personalrecycler.use") || permission.UserHasPermission(kvp.Key.ToString(), "personalrecycler.admin"))
                {
                    if (kvp.Value.available_recyclers < 0) kvp.Value.available_recyclers = 0;
                    if (config.recycler_credits_persist) kvp.Value.available_recyclers = kvp.Value.available_recyclers + config.start_recyclers;
                    else kvp.Value.available_recyclers = config.start_recyclers;
                }
                else if (kvp.Value.available_recyclers == 0) delete_users.Add(kvp.Key);
            }
            pcdData.private_recyclers.Clear();
            if (delete_users.Count > 0) foreach (var id in delete_users) pcdData.pentity.Remove(id);
            SaveData();
        }

        void OnServerInitialized(bool initial)
        {
            List<KeyValuePair<string, int>> Fixed = Pool.GetList<KeyValuePair<string, int>>();
            foreach (var kvp in config.max_override)
            {
                if (kvp.Key.StartsWith("personalrecycler.", StringComparison.OrdinalIgnoreCase))
                {
                    permission.RegisterPermission(kvp.Key, this);
                    continue;
                }
                Fixed.Add(kvp);
            }
            if (Fixed.Count > 0)
            {
                foreach (var kvp in Fixed)
                {
                    config.max_override.Remove(kvp.Key);
                    config.max_override.Add("personalrecycler." + kvp.Key, kvp.Value);
                    permission.RegisterPermission("personalrecycler." + kvp.Key, this);
                }
                SaveConfig();
            }
            Pool.FreeList(ref Fixed);
            
            List<Recycler> recyclers = Pool.GetList<Recycler>();
            foreach (var recycler in BaseNetworkable.serverEntities.OfType<Recycler>())
            {
                if (recycler.OwnerID > 0) recyclers.Add(recycler);
            }
            List<ulong> not_found_ids = Pool.GetList<ulong>();
            delayValue = config.ground_watch_check_delay;
            foreach (var kvp in pcdData.private_recyclers)
            {
                var found = false;
                foreach (var recycler in recyclers)
                {
                    if (recycler.net.ID.Value == kvp.Key)
                    {
                        var groundWatch = SetGroundWatch(recycler, false);
                        if (groundWatch) kvp.Value.groundWatch = true;
                        if (kvp.Value.groundWatch) AddGroundWatch(recycler);
                        found = true;
                        break;
                    }
                }
                if (!found) not_found_ids.Add(kvp.Key);
            }

            if (not_found_ids.Count > 0)
            {
                Puts($"Found {not_found_ids.Count} invalid entries.Cleaning up.");
                foreach (var kvp in pcdData.pentity)
                {
                    if (kvp.Value.recycler_ids.Count == 0) continue;
                    foreach (var id in not_found_ids)
                    {
                        kvp.Value.recycler_ids.Remove(id);
                    }
                }

                foreach (var id in not_found_ids)
                {
                    pcdData.private_recyclers.Remove(id);
                }
            }

            Pool.FreeList(ref recyclers);
            Pool.FreeList(ref not_found_ids);

            foreach (var kvp in pcdData.pentity)
                if (kvp.Value.available_recyclers < 0) kvp.Value.available_recyclers = 0;
        }

        private bool SetGroundWatch(Recycler recycler, bool addComponent = true)
        {
            if (!config.use_ground_watch) return false;
            RaycastHit rhit;
            var cast = Physics.Raycast(recycler.transform.position + new Vector3(0, 0.1f, 0), Vector3.down,
                out rhit, 1f, LayerMask.GetMask("Construction"));

            var entity = rhit.collider?.ToBaseEntity();
            if (entity != null)
            {
                if (addComponent) AddGroundWatch(recycler);
                return true;
            }
            return false;
        }

        void OnEntityDeath(Tugboat entity, HitInfo info)
        {
            List<Recycler> recyclers = Pool.GetList<Recycler>();
            foreach (var child in entity.children)
            {
                if (child == null) continue;
                if (child is Recycler)
                {
                    recyclers.Add(child as Recycler);
                    //child.Invoke(child.KillMessage, 0.05f);
                }
            }

            foreach (var recycler in recyclers)
            {
                var item = ConvertRecyclerToItem(recycler);
                if (item != null) item.DropAndTossUpwards(recycler.transform.position);
                recycler.Invoke(recycler.KillMessage, 0.05f);
            }

            Pool.FreeList(ref recyclers);
        }

        Item ConvertRecyclerToItem(Recycler recycler)
        {
            RecyclersInfo recyclerData;
            if (!pcdData.private_recyclers.TryGetValue(recycler.net.ID.Value, out recyclerData) || recycler.OwnerID == 0) return null;

            PlayerInfo ownerData;
            if (!pcdData.pentity.TryGetValue(recycler.OwnerID, out ownerData)) pcdData.pentity.Add(recycler.OwnerID, ownerData = new PlayerInfo(BasePlayer.Find(recycler.OwnerID.ToString())?.displayName ?? String.Empty));

            ownerData.recycler_ids.Remove(recycler.net.ID.Value);

            var item = SpawnRecycler(recyclerData != null ? recyclerData.condition - config.pickup_damage : config.start_health - config.pickup_damage);
            return item;
        }

        int GetMaxDeployableRecyclers(BasePlayer player)
        {
            if (config.max_deployed == 0) return 0;
            var max = config.max_deployed;
            foreach (var value in config.max_override)
            {
                if (value.Value > max && permission.UserHasPermission(player.UserIDString, value.Key))
                    max = value.Value;
                if (max == 0) return 0;
            }
            return max;
        }

        object CanBuild(Planner planner, Construction prefab, Construction.Target target)
        {
            var player = planner?.GetOwnerPlayer();
            if (player == null) return null;
            var item = planner?.GetItem();
            if (item == null || item.skin != recycler_skin || item.info.shortname != recycler_short) return null;
            if (item.name != recycler_name)
            {
                item.skin = 0;
                item.MarkDirty();
                return null;
            }
            if (!permission.UserHasPermission(player.UserIDString, "personalrecycler.place"))
            {
                PrintToChat(player, lang.GetMessage("NoPermsPlace", this, player.UserIDString));
                return true;
            }
            if (!pcdData.pentity.TryGetValue(player.userID, out var playerData)) return null;
            var max = GetMaxDeployableRecyclers(player);
            if (max == 0 || playerData.recycler_ids.Count < max) return null;

            PrintToChat(player, string.Format(lang.GetMessage("MaxReached", this, player.UserIDString), max));

            return true;
        }

        void OnEntityBuilt(Planner plan, GameObject go)
        {
            if (go == null) return;
            var entity = go.ToBaseEntity();
            if (entity == null) return;
            if (entity.skinID != recycler_skin) return;
            if (plan == null || plan.GetOwnerPlayer() == null) return;
            var player = plan.GetOwnerPlayer();
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(player.userID, out pi))
            {
                pcdData.pentity.Add(player.userID, pi = new PlayerInfo(player.displayName));
            }
            var rot = entity.transform.rotation;
            var recycler = GameManager.server.CreateEntity("assets/bundled/prefabs/static/recycler_static.prefab", entity.transform.position, rot, true) as Recycler;
            
            recycler.Spawn();
            recycler.radtownRecycleEfficiency = config.efficiency;
            recycler.safezoneRecycleEfficiency = config.efficiency;

            recycler.OwnerID = player.userID;
            var item = plan.GetItem();
            pi.recycler_ids.Add(recycler.net.ID.Value);

            timer.Once(0.5f, () =>
            {
                entity.Kill(BaseNetworkable.DestroyMode.None);
            });

            //timer.Once(0.1f, () =>
            //{
            //    entity.Kill(BaseNetworkable.DestroyMode.None);
            //});
            //
            NextTick(() =>
            {
                var parent = entity.GetParentEntity();
                if (parent == null || parent.ShortPrefabName != "tugboat")
                {
                    var groundWatch = SetGroundWatch(recycler);
                    pcdData.private_recyclers.Add(recycler.net.ID.Value, new RecyclersInfo(player.userID, item != null ? item.maxCondition : config.start_health, groundWatch));
                    return;
                }
                recycler.SetParent(parent, true, true);
                pcdData.private_recyclers.Add(recycler.net.ID.Value, new RecyclersInfo(player.userID, item != null ? item.maxCondition : config.start_health, false));

            });
        }

        object CanLootEntity(BasePlayer player, StorageContainer container)
        {
            if (!config.restrict_usage) return null;
            var recycler = container.GetEntity() as Recycler;
            if (player == null || container == null || recycler == null) return null;            

            if (recycler.OwnerID == 0 || !pcdData.private_recyclers.ContainsKey(recycler.net.ID.Value)) return null;

            if (player.userID != recycler.OwnerID && !permission.UserHasPermission(player.UserIDString, "personalrecycler.admin"))
            {
                if (!config.allow_team || (player.Team == null || player.Team.members == null || !player.Team.members.Contains(recycler.OwnerID)))
                {
                    PrintToChat(player, lang.GetMessage("CannotLoot", this, player.UserIDString));
                    return false;
                }
            }

            return null;            
        }

        #endregion

        #region Helpers

        void SpawnRecycler(BasePlayer player, float condition = -100)
        {
            var item = ItemManager.CreateByName(recycler_short, 1, recycler_skin);
            item.name = recycler_name;
            if (condition == -100) item.maxCondition = config.start_health;
            else if (condition <= 0)
            {
                item.maxCondition = condition;
                item.condition = 0;
                PrintToChat(player, lang.GetMessage("RecyclerBroken", this, player.UserIDString));
            }
            else item.maxCondition = condition;
            player.GiveItem(item);
        }

        Item SpawnRecycler(float condition = -100)
        {
            var item = ItemManager.CreateByName(recycler_short, 1, recycler_skin);
            item.name = recycler_name;
            if (condition == -100) item.maxCondition = config.start_health;
            else if (condition <= 0)
            {
                item.maxCondition = condition;
                item.condition = 0;                
            }
            else item.maxCondition = condition;
            return item;
        }

        private BasePlayer FindPlayerByName(string Playername, BasePlayer SearchingPlayer = null)
        {
            var targetList = BasePlayer.allPlayerList.Where(x => x.displayName.ToLower().Contains(Playername.ToLower())).OrderBy(x => x.displayName.Length);
            if (targetList.Count() == 1) return targetList.First();
            if (targetList.Count() > 1)
            {
                if (targetList.First().displayName.ToLower() == Playername.ToLower()) return targetList.First();
                if (SearchingPlayer != null) PrintToChat(SearchingPlayer, string.Format(lang.GetMessage("FindPlayerByName_TooMany", this, SearchingPlayer.UserIDString), String.Join(",", targetList.Select(x => x.displayName))));
                return null;
            }
            if (targetList.Count() == 0)
            {
                if (SearchingPlayer != null) PrintToChat(SearchingPlayer, string.Format(lang.GetMessage("FindPlayerByName_NoMatch", this, SearchingPlayer.UserIDString), Playername));
                return null;
            }
            return null;
        }

        private BasePlayer FindPlayerByID(ulong id)
        {
            return BasePlayer.allPlayerList.FirstOrDefault(x => x.userID == id) ?? null;           
        }

        private const int LAYER_TARGET = ~(1 << 2 | 1 << 3 | 1 << 4 | 1 << 10 | 1 << 18 | 1 << 28 | 1 << 29);
        private BaseEntity GetTargetEntity(BasePlayer player, float dist = 5f)
        {
            RaycastHit raycastHit;
            bool flag = Physics.Raycast(player.eyes.HeadRay(), out raycastHit, 100f, LAYER_TARGET);
            var targetEntity = flag ? raycastHit.GetEntity() : null;
            return targetEntity;
        }

        #endregion        

        #region API

        [ConsoleCommand("addrecycler")]
        void UseToken(ConsoleSystem.Arg arg)
        {
            // addrecycler id quantity
            if (arg == null || !arg.IsRcon) return;
            if (arg.Args.Length != 2) return;
            var id = Convert.ToUInt64(arg.Args[0]);
            if (!id.IsSteamId()) return;
            if (!arg.Args[1].IsNumeric()) return;
            var player = FindPlayerByID(id);
            PlayerInfo pi;
            if (!pcdData.pentity.TryGetValue(id, out pi)) pcdData.pentity.Add(id, pi = new PlayerInfo(player != null ? player.displayName : null));
            pi.available_recyclers += Convert.ToInt32(arg.Args[1]);
            if (player != null && player.IsConnected) PrintToChat(player, string.Format(lang.GetMessage("ConsoleRedeemed", this, player.UserIDString), pi.available_recyclers));
            if (config.credit_sound) EffectNetwork.Send(new Effect("assets/prefabs/deployable/vendingmachine/effects/vending-machine-purchase-human.prefab", player.transform.position, player.transform.position), player.net.connection);
            Puts($"Adding {Convert.ToInt32(arg.Args[1])} recycler(s) for {id}");
        }

        object SB_CanReskinItem(BasePlayer player, Item item, ulong newSkinID)
        {
            if (newSkinID != recycler_skin) return null;
            return lang.GetMessage("SkinboxReturn", this, player.UserIDString);
        }

        object SB_CanReskinDeployableWith(BasePlayer player, BaseEntity targetEntity, ItemDefinition targetItemDefintion, ulong newSkinID)
        {
            if (newSkinID != recycler_skin) return null;
            return lang.GetMessage("SkinboxReturn", this, player.UserIDString);
        }

        #endregion

        #region MonoBehaviour

        public static float delayValue;

        public void AddGroundWatch(BaseEntity entity)
        {
            var gameObject = entity.GetComponent<Ground_Watch>();
            if (gameObject != null) DestroyGroundWatch(entity);
            entity.gameObject.AddComponent<Ground_Watch>();
        }

        public static void DestroyRecycler(BaseEntity entity)
        {
            if (entity == null) return;
            DestroyGroundWatch(entity);
            entity.KillMessage();
        }

        public static void DestroyGroundWatch(BaseEntity entity)
        {            
            if (entity == null) return;
            var gameObject = entity.GetComponent<Ground_Watch>();
            if (gameObject != null) GameObject.Destroy(gameObject);
        }

        public class Ground_Watch : MonoBehaviour
        {
            private BaseEntity entity;
            private float groundCheckDelay;

            // Awake() is part of the Monobehaviour class.private void Awake()
            {
                entity = GetComponent<BaseEntity>();
                groundCheckDelay = Time.time + 5f;
            }

            // FixedUpdate() is also part of the monobehaviour class.public void FixedUpdate()
            {
                if (entity == null) return;
                if (groundCheckDelay < Time.time)
                {
                    groundCheckDelay = Time.time + delayValue;
                    DoGroundCheck();
                }
            }

            public void DoGroundCheck()
            {
                if (entity == null || entity.IsDestroyed || !entity.IsFullySpawned()) return;
                RaycastHit rhit;
                var cast = Physics.Raycast(entity.transform.position + new Vector3(0, 0.1f, 0), Vector3.down,
                    out rhit, 1f, LayerMask.GetMask("Construction"));

                var ent = rhit.collider?.ToBaseEntity();
                if (ent == null) DestroyRecycler(entity);
            }

            // OnDestroy() built into the monobehaviour class.private void OnDestroy()
            {
                enabled = false;
                CancelInvoke();
            }
        }

        #endregion
    }
}

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