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

FREE StackEverything : 1.2.5 1.2.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using UnityEngine;
using Facepunch;
using Rust;
namespace Oxide.Plugins {
    [Info("Stack Everything", "Cascade", "1.2.5")]
    [Description("Stack all entities and farm stacking with role-based limits and skin blacklists")]
    public class StackEverything : RustPlugin {
        private const string PermUse = "stackeverything.use";
        private const string LangPrefix = "StackEverything";
        private readonly HashSet<ulong> spawnedByPlugin = new HashSet<ulong>();
        private readonly HashSet<ulong> ownersStacking = new HashSet<ulong>();
        private ConfigData config;
        private bool debug;
        private class VersionNumberData {
            public int Major;
            public int Minor;
            public int Patch;
        }
        private void OnEntityKill(BaseNetworkable net) {
            var entity = net as BaseEntity;
            if (entity?.net == null) return;
            spawnedByPlugin.Remove(entity.net.ID.Value);
        }
        private class RoleConfig {
            public int Priority;
            public int MaximumNumberOfStackableEntities;
            public List<string> ExcludeStackingOfTheseEntities = new List<string>();
            public Dictionary<string, int> MaximumStackNumberPerEntity = new Dictionary<string, int>();
        }
        private class StackItem {
            public string DisplayName;
            public string ItemName;
            public int ItemId;
            public bool EnableStacking;
            public string PrefabName;
            public float RadiusCheck;
            public float ColliderHeight;
            public float YOffset;
            public string EffectName;
        }
        private class ConfigData {
            public bool UseClanTeam;
            public bool ShareGroupWithClanTeamMembers;
            public bool EnableDynamicAutoStacking = true;
            public List<ulong> SpawnSkinIdBlacklist = new List<ulong>();
            public List<ulong> StackingSkinIdBlacklist = new List<ulong>();
            public Dictionary<string, RoleConfig> RolePermission = new Dictionary<string, RoleConfig>();
            public List<StackItem> StackableItems = new List<StackItem>();
            public VersionNumberData VersionNumber = new VersionNumberData {
                Major = 1, Minor = 2, Patch = 5
            }
            ;
        }
        protected override void LoadDefaultConfig() {
            config = new ConfigData {
                UseClanTeam = true, ShareGroupWithClanTeamMembers = false, EnableDynamicAutoStacking = true, RolePermission = new Dictionary<string, RoleConfig> {
                    ["default"]
                    = new RoleConfig {
                        Priority = 100, MaximumNumberOfStackableEntities = 2
                    }
                    , ["vip1"] = new RoleConfig {
                        Priority = 1, MaximumNumberOfStackableEntities = 4
                    }
                    , ["vip2"] = new RoleConfig {
                        Priority = 2, MaximumNumberOfStackableEntities = 6
                    }
                    , ["vip3"] = new RoleConfig {
                        Priority = 3, MaximumNumberOfStackableEntities = 10
                    }
                }
                , StackableItems = new List<StackItem> {
                    new StackItem {
                        DisplayName = "Large Water Catcher", ItemName = "water.catcher.large", ItemId = -1100168350, EnableStacking = true, PrefabName = "assets/prefabs/deployable/water catcher/water_catcher_large.prefab", RadiusCheck = 0.1f, ColliderHeight = 4.168319f, YOffset = 4.1f, EffectName = "assets/prefabs/deployable/water catcher/effects/water-catcher-large-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Small Water Catcher", ItemName = "water.catcher.small", ItemId = -132247350, EnableStacking = true, PrefabName = "assets/prefabs/deployable/water catcher/water_catcher_small.prefab", RadiusCheck = 0.1f, ColliderHeight = 2.67044f, YOffset = 2.5f, EffectName = "assets/prefabs/deployable/water catcher/effects/water-catcher-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Large Wood Box", ItemName = "box.wooden.large", ItemId = 833533164, EnableStacking = true, PrefabName = "assets/prefabs/deployable/large wood storage/box.wooden.large.prefab", RadiusCheck = 0.1f, ColliderHeight = 0.790511f, YOffset = 0.76f, EffectName = "assets/prefabs/deployable/large wood storage/effects/large-wood-box-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Wood Storage Box", ItemName = "box.wooden", ItemId = -180129657, EnableStacking = true, PrefabName = "assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab", RadiusCheck = 0.1f, ColliderHeight = 0.5552952f, YOffset = 0.5552952f, EffectName = "assets/prefabs/deployable/woodenbox/effects/wooden-box-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Furnace", ItemName = "furnace", ItemId = -1999722522, EnableStacking = true, PrefabName = "assets/prefabs/deployable/furnace/furnace.prefab", RadiusCheck = 0.1f, ColliderHeight = 1.6f, YOffset = 1.44f, EffectName = "assets/prefabs/deployable/furnace/effects/furnace-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Electric Furnace", ItemName = "electric.furnace", ItemId = -1196547867, EnableStacking = true, PrefabName = "assets/prefabs/deployable/playerioents/electricfurnace/electricfurnace.deployed.prefab", RadiusCheck = 0.1f, ColliderHeight = 1.2f, YOffset = 1.15f, EffectName = "assets/prefabs/deployable/playerioents/electricfurnace/effects/electric-furnace-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Composter", ItemName = "composter", ItemId = -1488398114, EnableStacking = true, PrefabName = "assets/prefabs/deployable/composter/composter.prefab", RadiusCheck = 0.1f, ColliderHeight = 1.64f, YOffset = 1.54f, EffectName = "assets/prefabs/deployable/furnace/effects/furnace-deploy.prefab"
                    }
                    , new StackItem {
                        DisplayName = "Locker", ItemName = "locker", ItemId = -110921842, EnableStacking = true, PrefabName = "assets/prefabs/deployable/locker/locker.deployed.prefab", RadiusCheck = 0.1f, ColliderHeight = 2.3f, YOffset = 2.238f, EffectName = "assets/prefabs/deployable/locker/effects/locker-deploy.prefab"
                    }
                }
            }
            ;
            SaveConfig();
        }
        private void Init() {
            LoadConfigValues();
            permission.RegisterPermission(PermUse, this);
            foreach (var role in config.RolePermission.Keys) permission.RegisterPermission($"stackeverything.{role}", this);
            lang.RegisterMessages(new Dictionary<string, string> {
                [$"{LangPrefix}.NoPermission"]
                = "Нет прав", [$"{LangPrefix}.Disabled"] = "Стакинг отключен", [$"{LangPrefix}.MaxReached"] = "Достигнут предел стакинга"
            }
            , this, "ru");
            lang.RegisterMessages(new Dictionary<string, string> {
                [$"{LangPrefix}.NoPermission"]
                = "No permission", [$"{LangPrefix}.Disabled"] = "Stacking disabled", [$"{LangPrefix}.MaxReached"] = "Max stacking reached"
            }
            , this, "en");
        }
        private void LoadConfigValues() {
            try {
                config = Config.ReadObject<ConfigData>();
            }
            catch {
                LoadDefaultConfig();
            }
            if (config.VersionNumber == null) config.VersionNumber = new VersionNumberData {
                Major = 1, Minor = 2, Patch = 5
            }
            ;
        }
        protected override void SaveConfig() {
            Config.WriteObject(config, true);
        }
        private void OnEntityBuilt(Planner planner, GameObject go) {
            if (planner == null || go == null) return;
            var player = planner.GetOwnerPlayer();
            if (player == null) return;
            var entity = go.GetComponent<BaseEntity>();
            if (entity == null) return;
            if (debug) SendReply(player, $"StackEverything: OnEntityBuilt {entity.PrefabName}");
            TryStack(player, entity);
        }
        private void OnEntitySpawned(BaseNetworkable net) {
            var entity = net as BaseEntity;
            if (entity == null) return;
            if (entity.net != null && spawnedByPlugin.Contains(entity.net.ID.Value)) return;
            var ownerId = entity.OwnerID;
            if (ownerId == 0) return;
            if (ownersStacking.Contains(ownerId)) return;
            var player = BasePlayer.FindByID(ownerId) ?? BasePlayer.FindSleeping(ownerId);
            if (player == null) return;
            if (debug) SendReply(player, $"StackEverything: OnEntitySpawned {entity.PrefabName}");
            TryStack(player, entity);
        }
        private void TryStack(BasePlayer player, BaseEntity baseEntity) {
            if (!permission.UserHasPermission(player.UserIDString, PermUse)) return;
            if (!ownersStacking.Add(player.userID)) return;
            try {
                var prefab = baseEntity.PrefabName;
                var itemCfg = config.StackableItems.FirstOrDefault(x => x.EnableStacking && string.Equals(x.PrefabName, prefab, StringComparison.OrdinalIgnoreCase));
                if (itemCfg == null) {
                    if (!config.EnableDynamicAutoStacking) return;
                    var h = GetColliderHeight(baseEntity);
                    itemCfg = new StackItem {
                        DisplayName = baseEntity.ShortPrefabName, ItemName = string.Empty, ItemId = 0, EnableStacking = true, PrefabName = prefab, RadiusCheck = 0.05f, ColliderHeight = h, YOffset = h, EffectName = string.Empty
                    }
                    ;
                    if (debug) SendReply(player, $"StackEverything: Dynamic config for {prefab}, height {h:F2}");
                }
                if (config.StackingSkinIdBlacklist != null && config.StackingSkinIdBlacklist.Contains(baseEntity.skinID)) return;
                var role = ResolvePlayerRole(player);
                if (role == null) return;
                if (role.ExcludeStackingOfTheseEntities != null && role.ExcludeStackingOfTheseEntities.Any(x => string.Equals(x, prefab, StringComparison.OrdinalIgnoreCase))) return;
                var maxByRole = role.MaximumNumberOfStackableEntities;
                var maxByEntity = 0;
                if (role.MaximumStackNumberPerEntity != null) {
                    if (role.MaximumStackNumberPerEntity.TryGetValue(prefab, out var m)) maxByEntity = m;
                }
                var max = Math.Max(0, Math.Max(maxByEntity, maxByRole));
                if (max > 5) max = 5;
                if (max <= 1) return;
                var teamCheckOwner = baseEntity.OwnerID;
                if (config.UseClanTeam && !CanStackOnOwnership(player, baseEntity)) return;
                var basePos = baseEntity.transform.position;
                var baseRot = baseEntity.transform.rotation;
                var skin = baseEntity.skinID;
                if (config.SpawnSkinIdBlacklist != null && config.SpawnSkinIdBlacklist.Contains(skin)) skin = 0;
                if (debug) SendReply(player, $"StackEverything: Stacking {prefab} up to {max} with skin {skin}");
                for (var i = 1; i < max; i++) {
                    var stackHeight = itemCfg.YOffset > 0f ? itemCfg.YOffset : (itemCfg.ColliderHeight > 0f ? itemCfg.ColliderHeight : GetColliderHeight(baseEntity));
                    if (stackHeight <= 0f) stackHeight = 1f;
                    var spawnPos = basePos + new Vector3(0f, stackHeight * i, 0f);
                    if (!IsPositionValid(spawnPos, itemCfg.RadiusCheck <= 0f ? 0.05f : itemCfg.RadiusCheck, baseEntity)) break;
                    var ent = GameManager.server.CreateEntity(itemCfg.PrefabName, spawnPos, baseRot);
                    if (ent == null) break;
                    ent.skinID = skin;
                    ent.OwnerID = player.userID;
                    ent.Spawn();
                    if (ent.net != null) spawnedByPlugin.Add(ent.net.ID.Value);
                    if (!string.IsNullOrEmpty(itemCfg.EffectName)) Effect.server.Run(itemCfg.EffectName, spawnPos);
                    if (debug) SendReply(player, $"StackEverything: Spawned at {spawnPos}");
                }
            }
            finally {
                ownersStacking.Remove(player.userID);
            }
        }
        private float GetColliderHeight(BaseEntity entity) {
            float height = 0f;
            var colliders = entity.GetComponentsInChildren<Collider>();
            if (colliders != null && colliders.Length > 0) {
                for (int i = 0; i < colliders.Length; i++) {
                    var c = colliders[i];
                    if (c == null) continue;
                    var sizeY = c.bounds.size.y;
                    if (sizeY > height) height = sizeY;
                }
            }
            if (height <= 0f) height = 1f;
            return height;
        }
        private bool IsPositionValid(Vector3 pos, float radius, BaseEntity ignore) {
            var hits = Pool.GetList<Collider>();
            try {
                Vis.Colliders(pos, radius, hits, Layers.Mask.Prevent_Building | Layers.Mask.Trigger);
                if (hits.Count == 0) return true;
                for (int i = 0; i < hits.Count; i++) {
                    var h = hits[i];
                    if (h == null) continue;
                    if (ignore != null && h.transform != null && (h.transform == ignore.transform || h.transform.root == ignore.transform.root)) continue;
                    return false;
                }
                return true;
            }
            finally {
                hits.Clear();
                Pool.FreeList(ref hits);
            }
        }
        private RoleConfig ResolvePlayerRole(BasePlayer player) {
            var roles = new List<(string name, RoleConfig cfg)>();
            foreach (var kvp in config.RolePermission) {
                if (permission.UserHasPermission(player.UserIDString, $"stackeverything.{kvp.Key}")) roles.Add((kvp.Key, kvp.Value));
            }
            if (config.UseClanTeam && config.ShareGroupWithClanTeamMembers) {
                RelationshipManager.PlayerTeam team = null;
                var teams = RelationshipManager.ServerInstance?.teams;
                if (teams != null && teams.TryGetValue(player.currentTeam, out team) && team != null) {
                    foreach (var member in team.members) {
                        var p = BasePlayer.FindByID(member) ?? BasePlayer.FindSleeping(member);
                        if (p == null) continue;
                        foreach (var kvp in config.RolePermission) {
                            if (permission.UserHasPermission(p.UserIDString, $"stackeverything.{kvp.Key}") && roles.All(r => r.name != kvp.Key)) roles.Add((kvp.Key, kvp.Value));
                        }
                    }
                }
            }
            if (roles.Count == 0 && config.RolePermission.TryGetValue("default", out var def)) return def;
            var selected = roles.OrderBy(r => r.cfg.Priority).FirstOrDefault();
            return selected.cfg;
        }
        [ConsoleCommand("stackeverything.debug")]
        private void CmdDebug(ConsoleSystem.Arg arg) {
            if (arg == null || arg.Connection == null) return;
            var player = arg.Player();
            if (player == null || !player.IsAdmin) return;
            if (arg.Args != null && arg.Args.Length > 0) {
                debug = arg.GetInt(0) != 0;
            }
            SendReply(player, $"StackEverything debug: {(debug ? "ON" : "OFF")}");
        }
        private bool CanStackOnOwnership(BasePlayer player, BaseEntity target) {
            if (target == null) return true;
            if (target.OwnerID == 0) return true;
            if (target.OwnerID == player.userID) return true;
            if (!config.UseClanTeam) return false;
            RelationshipManager.PlayerTeam team = null;
            var teams = RelationshipManager.ServerInstance?.teams;
            if (teams == null || !teams.TryGetValue(player.currentTeam, out team) || team == null) return false;
            return team.members != null && team.members.Contains(target.OwnerID);
        }
    }
}

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