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

FREE SpawnControl : 1.0.6 1.0.6

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Configuration;
namespace Oxide.Plugins {
    [Info("SpawnControl", "Fujikura", "1.0.6", ResourceId = 18)]
    class SpawnControl : RustPlugin {
        bool Changed = false;
        bool _loaded;
        bool _startup;
        bool _terrainReady;
        bool heartbeatOn = false;
        double lastMinute;
        bool newSave;
        bool runningEnforceLimits;
        bool runningSpawnKill;
        bool runningSpawnLowerDensity;
        bool runningSpawnRaiseDensity;
        bool runningSpawnFill;
        Dictionary <string, object> SpawnPopulation = new Dictionary <string, object>();
        Dictionary <string, object> SpawnGroups = new Dictionary <string, object>();
        Dictionary<string, object> spawnDefaults = new Dictionary<string, object>();
        List<string> PopulationNames = new List<string>();
        Dictionary <string, int> FillPopulations = new Dictionary <string, int>();
        Dictionary <string, int> FillJobs = new Dictionary <string, int>();
        DynamicConfigFile defaultSpawnPops;
        DynamicConfigFile getFile(string file) => Interface.Oxide.DataFileSystem.GetDatafile($"{file}");
        bool chkFile(string file) => Interface.Oxide.DataFileSystem.ExistsDatafile($"{file}");
        FieldInfo _PrefabsField = typeof (SpawnPopulation).GetField("Prefabs", BindingFlags.Instance | BindingFlags.NonPublic);
        FieldInfo _targetDensity = typeof (SpawnPopulation).GetField("_targetDensity", BindingFlags.Instance | BindingFlags.NonPublic);
        FieldInfo _SpawnInstances = typeof (SpawnGroup).GetField("spawnInstances", BindingFlags.Instance | BindingFlags.NonPublic);
        FieldInfo _SpawnDistributions = typeof(SpawnHandler).GetField("SpawnDistributions", (BindingFlags.Instance | BindingFlags.NonPublic));
        FieldInfo _spawnClock = typeof(SpawnGroup).GetField("spawnClock", BindingFlags.NonPublic | BindingFlags.Instance);
        MethodInfo _OnDestroy = typeof(SpawnPointInstance).GetMethod("OnDestroy", BindingFlags.NonPublic | BindingFlags.Instance);
        bool enableSpawnGroups;
        bool enableGroupTickData;
        bool enablePopulationPrefabs;
        bool normalizeDefaultVariables;
        bool initialFillPopulations;
        bool reloadWithIncludedFill;
        bool logJobsToConsole;
        bool fixBarricadeStacking;
        float tickInterval;
        int minSpawnsPerTick;
        int maxSpawnsPerTick;
        object GetConfig(string menu, string datavalue, object defaultValue) {
            var data = Config[menu] as Dictionary<string, object>;
            if (data == null) {
                data = new Dictionary<string, object>();
                Config[menu] = data;
                Changed = true;
            }
            object value;
            if (!data.TryGetValue(datavalue, out value)) {
                value = defaultValue;
                data[datavalue] = value;
                Changed = true;
            }
            return value;
        }
        void LoadVariables() {
            SpawnPopulation = (Dictionary <string, object>)GetConfig("Spawn", "Population", new Dictionary<string, object>());
            SpawnGroups = (Dictionary <string, object>)GetConfig("Spawn", "Groups", new Dictionary<string, object>());
            enableSpawnGroups = Convert.ToBoolean(GetConfig("Generic", "enableSpawnGroups", false));
            enableGroupTickData = Convert.ToBoolean(GetConfig("Generic", "enableGroupTickData", false));
            enablePopulationPrefabs = Convert.ToBoolean(GetConfig("Generic", "enablePopulationPrefabs", false));
            normalizeDefaultVariables = Convert.ToBoolean(GetConfig("Generic", "normalizeDefaultVariables", true));
            initialFillPopulations = Convert.ToBoolean(GetConfig("Generic", "initialFillPopulations", true));
            reloadWithIncludedFill = Convert.ToBoolean(GetConfig("Generic", "reloadWithIncludedFill", false));
            logJobsToConsole = Convert.ToBoolean(GetConfig("Generic", "logJobsToConsole", true));
            fixBarricadeStacking = Convert.ToBoolean(GetConfig("Generic", "fixBarricadeStacking", true));
            tickInterval = Convert.ToSingle(GetConfig("Handler", "tickInterval", 120.0f));
            minSpawnsPerTick = Convert.ToInt32(GetConfig("Handler", "minSpawnsPerTick", 100));
            maxSpawnsPerTick = Convert.ToInt32(GetConfig("Handler", "maxSpawnsPerTick", 200));
            if (!Changed) return;
            SaveConfig();
            Changed = false;
        }
        protected override void LoadDefaultConfig() {
            Config.Clear();
            LoadVariables();
        }
        void Init() {
            LoadVariables();
            _terrainReady = false;
            _startup = true;
            if (normalizeDefaultVariables) {
                ConVar.Spawn.max_density = 1f;
                ConVar.Spawn.max_rate = 1f;
                ConVar.Spawn.min_density = 0.5f;
                ConVar.Spawn.min_rate = 0.5f;
            }
            newSave = false;
            lastMinute = DateTime.UtcNow.Minute;
        }
        void OnNewSave(string strFilename) {
            newSave = true;
        }
        void Unload() {
            ServerMgr.Instance.StopCoroutine("SpawnKill");
            ServerMgr.Instance.StopCoroutine("SpawnFill");
            ServerMgr.Instance.StopCoroutine("EnforceLimits");
            ServerMgr.Instance.StopCoroutine("SpawnLowerDensity");
            ServerMgr.Instance.StopCoroutine("SpawnRaiseDensity");
            runningEnforceLimits = false;
            runningSpawnKill = false;
            runningSpawnLowerDensity = false;
            runningSpawnRaiseDensity = false;
            runningSpawnFill = false;
        }
        void OnTerrainInitialized() {
            if (_startup && !newSave) {
                _terrainReady = true;
                GetPopulationDefaults();
            }
            SpawnHandler.Instance.MaxSpawnsPerTick = maxSpawnsPerTick;
            SpawnHandler.Instance.MinSpawnsPerTick = minSpawnsPerTick;
            if (SpawnHandler.Instance.TickInterval != tickInterval) {
                SpawnHandler.Instance.StopCoroutine("SpawnTick");
                SpawnHandler.Instance.TickInterval = tickInterval;
                SpawnHandler.Instance.StartCoroutine("SpawnTick");
            }
            if (SpawnPopulation != null && SpawnPopulation.Count > 0) SpawnPopLoad();
            else SpawnPopDefaults();
            if (enableSpawnGroups) {
                if (SpawnGroups != null && SpawnGroups.Count > 0) SpawnGroupLoad();
                else SpawnGroupDefaults();
            }
            if (_startup && !newSave) _terrainReady = true;
            _loaded = true;
        }
        void GetPopulationDefaults() {
            List<SpawnPopulation> spawnPopulations = FileSystem.LoadAll<SpawnPopulation>("Assets/content/properties/spawnpopulation/").ToList();
            spawnDefaults = new Dictionary<string, object>();
            foreach (var pop in spawnPopulations) {
                spawnDefaults.Add(pop.name, pop.TargetDensity);
            }
            defaultSpawnPops = getFile($"{this.Title}_defaults");
            defaultSpawnPops.Clear();
            defaultSpawnPops.Set("Backup", spawnDefaults);
            defaultSpawnPops.Save();
        }
        void LoadPopulationDefaults() {
            if (spawnDefaults == null || spawnDefaults.Count == 0) {
                spawnDefaults = new Dictionary<string, object>();
                defaultSpawnPops = getFile($"{this.Title}_defaults");
                spawnDefaults = defaultSpawnPops["Backup"] as Dictionary<string, object>;
            }
        }
        void OnServerInitialized() {
            _startup = false;
            if (!_loaded) OnTerrainInitialized();
            GetPopulationNames();
            if (_terrainReady && initialFillPopulations) NextTick(() => SpawnHandler.Instance.FillPopulations());
            if (FillJobs.Count > 0) Puts($"Planned {FillJobs.Count} job(s) for spawn population");
            FixBarricades();
            LoadPopulationDefaults();
        }
        void OnTick() {
            if (!_loaded || !heartbeatOn || lastMinute == DateTime.UtcNow.Minute || CheckRoutines() ) return;
            lastMinute = DateTime.UtcNow.Minute;
            foreach (var job in FillJobs.ToList()) {
                if ((int)FillJobs[job.Key] < 1) {
                    timer.Once(2f, ()=> ConsoleSystem.Run(ConsoleSystem.Option.Server.Quiet(), "sc.fill", new object[] {
                        job.Key.ToString(), "auto"
                    }
                    ));
                    FillJobs[job.Key] = FillPopulations[job.Key];
                }
                else FillJobs[job.Key] = (int)job.Value -1;
            }
        }
        bool CheckRoutines() {
            if (runningEnforceLimits || runningSpawnKill || runningSpawnLowerDensity || runningSpawnRaiseDensity || runningSpawnFill) return true;
            return false;
        }
        void GetPopulationNames() {
            PopulationNames = new List<string>();
            foreach (var pop in SpawnHandler.Instance.SpawnPopulations) PopulationNames.Add(pop.name);
        }
        void SpawnPopDefaults() {
            var _handler = SpawnHandler.Instance;
            var data = new Dictionary<string, object>();
            SpawnPopulation.Clear();
            foreach (var population in _handler.SpawnPopulations) {
                var populationdata = new Dictionary<string, object>();
                populationdata.Add("spawndensity", population.TargetDensity);
                populationdata.Add("spawnrate", population.SpawnRate);
                populationdata.Add("spawnlimits", population.EnforcePopulationLimits);
                populationdata.Add("spawnfillheartbeat", 0);
                if (enablePopulationPrefabs) {
                    var prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(population);
                    if (prefabs == null || prefabs.Length == 0) {
                        if (!string.IsNullOrEmpty(population.ResourceFolder)) _PrefabsField.SetValue(population, Prefab.Load<Spawnable>(string.Concat("assets/bundled/prefabs/autospawn/", population.ResourceFolder), GameManager.server, PrefabAttribute.server));
                        if (population.ResourceList != null && population.ResourceList.Length > 0) _PrefabsField.SetValue(population, Prefab.Load<Spawnable>(population.ResourceList.Select(x => x.resourcePath).ToArray(), GameManager.server, PrefabAttribute.server));
                    }
                    prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(population);
                    var counts = prefabs.GroupBy(x => x.Name).ToDictionary(g => g.Key, g => g.Count());
                    var prefabdata = new Dictionary<string, object>();
                    foreach (var prefab in counts) prefabdata.Add(prefab.Key, prefab.Value );
                    populationdata.Add("spawnweights", prefabdata);
                }
                data.Add(population.name, populationdata);
            }
            SpawnPopulation = new Dictionary<string, object>(data);
            Config["Spawn", "Population"] = SpawnPopulation;
            Config.Save();
            Puts($"Created SpawnPopulation with '{data.Count}' populations.");
        }
        void SpawnPopLoad() {
            var _handler = SpawnHandler.Instance;
            Dictionary<string, object> data = new Dictionary<string, object>(SpawnPopulation);
            if (data == null || data.Count() == 0) {
                SpawnPopDefaults();
                return;
            }
            List<string> populationnames = new List<string>();
            foreach (var population in _handler.SpawnPopulations) populationnames.Add(population.name);
            bool changed = false;
            foreach (var population in data.ToList()) if (!populationnames.Contains(population.Key.ToString())) {
                Puts($"Invalid SpawnPopulation removed: {population.Key}");
                data.Remove(population.Key);
                changed = true;
            }
            foreach (var population in _handler.SpawnPopulations) {
                var name = population.name;
                if (name == null) continue;
                if (!data.ContainsKey(name)) {
                    var populationdata = new Dictionary<string, object>();
                    populationdata.Add("spawndensity", population.TargetDensity);
                    populationdata.Add("spawnrate", population.SpawnRate);
                    populationdata.Add("spawnlimits", population.EnforcePopulationLimits);
                    populationdata.Add("spawnfillheartbeat", 0);
                    if (enablePopulationPrefabs) {
                        var prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(population);
                        if (prefabs == null || prefabs.Length == 0) {
                            if (!string.IsNullOrEmpty(population.ResourceFolder)) _PrefabsField.SetValue(population, Prefab.Load<Spawnable>(string.Concat("assets/bundled/prefabs/autospawn/", population.ResourceFolder), GameManager.server, PrefabAttribute.server));
                            if (population.ResourceList != null && population.ResourceList.Length > 0) _PrefabsField.SetValue(population, Prefab.Load<Spawnable>(population.ResourceList.Select(x => x.resourcePath).ToArray(), GameManager.server, PrefabAttribute.server));
                        }
                        prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(population);
                        var counts = prefabs.GroupBy(x => x.Name).ToDictionary(g => g.Key, g => g.Count());
                        var prefabdata = new Dictionary<string, object>();
                        foreach (var prefab in counts) prefabdata.Add(prefab.Key, prefab.Value );
                        populationdata.Add("spawnweights", prefabdata);
                    }
                    data.Add(name, populationdata);
                    Puts($"Added new SpawnPopulation: {name}");
                    changed = true;
                }
            }
            SpawnPopulation = new Dictionary<string, object>(data);
            if (changed) {
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
            }
            bool addedPrefabs = false;
            foreach (var spawnPopulation in _handler.SpawnPopulations) {
                object spawndata;
                if (!data.TryGetValue(spawnPopulation.name, out spawndata)) continue;
                Dictionary<string, object> spawnData = spawndata as Dictionary<string, object>;
                if (enablePopulationPrefabs && !spawnData.ContainsKey("spawnweights")) {
                    var prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(spawnPopulation);
                    if (prefabs == null || prefabs.Length == 0) {
                        if (!string.IsNullOrEmpty(spawnPopulation.ResourceFolder)) _PrefabsField.SetValue(spawnPopulation, Prefab.Load<Spawnable>(string.Concat("assets/bundled/prefabs/autospawn/", spawnPopulation.ResourceFolder), GameManager.server, PrefabAttribute.server));
                        if (spawnPopulation.ResourceList != null && spawnPopulation.ResourceList.Length > 0) _PrefabsField.SetValue(spawnPopulation, Prefab.Load<Spawnable>(spawnPopulation.ResourceList.Select(x => x.resourcePath).ToArray(), GameManager.server, PrefabAttribute.server));
                    }
                    prefabs = (Prefab<Spawnable>[])_PrefabsField.GetValue(spawnPopulation);
                    var counts = prefabs.GroupBy(x => x.Name).ToDictionary(g => g.Key, g => g.Count());
                    var prefabdata = new Dictionary<string, object>();
                    foreach (var prefab in counts) prefabdata.Add(prefab.Key, prefab.Value );
                    spawnData.Add("spawnweights", prefabdata);
                    addedPrefabs = true;
                }
                if (enablePopulationPrefabs) {
                    Dictionary<string, object> prefabData = spawnData["spawnweights"] as Dictionary<string, object>;
                    var prefabs = new List<Prefab<Spawnable>>();
                    foreach (var prefab in prefabData) {
                        var gameObject = GameManager.server.FindPrefab(prefab.Key);
                        var component = gameObject?.GetComponent<Spawnable>();
                        if (component == null) continue;
                        for (var i = 0; i < Convert.ToInt32(prefab.Value);
                        i++) prefabs.Add(new Prefab<Spawnable>(prefab.Key, gameObject, component, GameManager.server, PrefabAttribute.server));
                    }
                    _PrefabsField.SetValue(spawnPopulation, prefabs.ToArray());
                }
                spawnPopulation.EnforcePopulationLimits = Convert.ToBoolean(spawnData["spawnlimits"]);
                spawnPopulation.SpawnRate = Convert.ToSingle(spawnData["spawnrate"]);
                _targetDensity.SetValue(spawnPopulation, Convert.ToSingle(spawnData["spawndensity"]));
                if ((int)spawnData["spawnfillheartbeat"] > 0 ) {
                    FillPopulations.Add(spawnPopulation.name, (int)spawnData["spawnfillheartbeat"]);
                    heartbeatOn = true;
                }
            }
            if (addedPrefabs) {
                SpawnPopulation = new Dictionary<string, object>(data);
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
            }
            if (heartbeatOn) FillJobs = new Dictionary<string, int>(FillPopulations);
            Puts($"Loaded '{data.Count}' SpawnPopulations");
        }
        void SpawnGroupDefaults() {
            if (!enableSpawnGroups) return;
            SpawnGroups.Clear();
            foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>()) {
                if (SpawnGroups.ContainsKey(PrefabCut(monument.name))) continue;
                foreach(var group in monument.gameObject.GetComponentsInChildren<SpawnGroup>()) {
                    if (group.name.StartsWith("door_barricade") || group.name.StartsWith("Barricades") || group.name.StartsWith("Ore")) continue;
                    Dictionary <string, object> spawner = new Dictionary <string, object>();
                    spawner.Add("_refName", group.name);
                    spawner.Add("_refNumber", group.maxPopulation);
                    spawner.Add("delayMin", group.respawnDelayMin);
                    spawner.Add("delayMax", group.respawnDelayMax);
                    if (enableGroupTickData) {
                        spawner.Add("perTickMin", group.numToSpawnPerTickMin);
                        spawner.Add("perTickMax", group.numToSpawnPerTickMax);
                    }
                    if (!SpawnGroups.ContainsKey(PrefabCut(monument.name))) SpawnGroups.Add(PrefabCut(monument.name), new List<object>());
                    (SpawnGroups[PrefabCut(monument.name)] as List<object>).Add(spawner);
                }
            }
            Config["Spawn", "Groups"] = SpawnGroups;
            Config.Save();
            Puts($"Created '{SpawnGroups.Count()}' SpawnGroups");
        }
        void SpawnGroupLoad() {
            if (!enableSpawnGroups) return;
            if (SpawnGroups == null || SpawnGroups.Count() == 0) {
                SpawnGroupDefaults();
                return;
            }
            bool addedMonument = false;
            bool addedGroup = false;
            bool addedTickData = false;
            var _handler = SpawnHandler.Instance;
            List<string> alreadySeenMonuments = new List<string>();
            foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>()) {
                if (alreadySeenMonuments.Contains(monument.name)) continue;
                alreadySeenMonuments.Add(monument.name);
                MethodInfo spawnMethod = null;
                if (!SpawnGroups.ContainsKey(PrefabCut(monument.name))) {
                    foreach(var group in monument.gameObject.GetComponentsInChildren<SpawnGroup>()) {
                        if (group.name.StartsWith("door_barricade") || group.name.StartsWith("Barricades") || group.name.StartsWith("Ore")) continue;
                        Dictionary <string, object> spawner = new Dictionary <string, object>();
                        spawner.Add("_refName", group.name);
                        spawner.Add("_refNumber", group.maxPopulation);
                        spawner.Add("delayMin", group.respawnDelayMin);
                        spawner.Add("delayMax", group.respawnDelayMax);
                        if (enableGroupTickData) {
                            spawner.Add("perTickMin", group.numToSpawnPerTickMin);
                            spawner.Add("perTickMax", group.numToSpawnPerTickMax);
                        }
                        if (!SpawnGroups.ContainsKey(PrefabCut(monument.name))) {
                            SpawnGroups.Add(PrefabCut(monument.name), new List<object>());
                            addedMonument = true;
                        }
                        (SpawnGroups[PrefabCut(monument.name)] as List<object>).Add(spawner);
                    }
                    continue;
                }
                List<object> filegroups = (SpawnGroups[PrefabCut(monument.name)] as List<object>);
                foreach(var group in monument.gameObject.GetComponentsInChildren<SpawnGroup>()) {
                    if (group.name.StartsWith("door_barricade") || group.name.StartsWith("Barricades") || group.name.StartsWith("Ore")) continue;
                    bool groupMatch = false;
                    foreach (var filegroup in filegroups) {
                        Dictionary<string, object> groupdata = filegroup as Dictionary<string, object>;
                        if ((string)groupdata["_refName"] == group.name && (int)groupdata["_refNumber"] == group.maxPopulation) {
                            group.respawnDelayMin = Convert.ToSingle(groupdata["delayMin"]);
                            group.respawnDelayMax = Convert.ToSingle(groupdata["delayMax"]);
                            if (enableGroupTickData) {
                                if (!groupdata.ContainsKey("perTickMin")) {
                                    groupdata.Add("perTickMin", group.numToSpawnPerTickMin);
                                    addedTickData = true;
                                }
                                if (!groupdata.ContainsKey("perTickMax")) {
                                    groupdata.Add("perTickMax", group.numToSpawnPerTickMax);
                                    addedTickData = true;
                                }
                                group.numToSpawnPerTickMin = (int)groupdata["perTickMin"];
                                group.numToSpawnPerTickMax = (int)groupdata["perTickMax"];
                            }
                            foreach (var method in group.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic )) {
                                if (!method.Name.Contains("Spawn") || method.GetParameters().Length > 0) continue;
                                spawnMethod = method;
                                break;
                            }
                            Action action = delegate {
                                spawnMethod.Invoke(group, null);
                            }
                            ;
                            LocalClock spawnClock = (LocalClock)_spawnClock.GetValue(group);
                            spawnClock = new LocalClock();
                            spawnClock.Add(group.GetSpawnDelta(), group.GetSpawnVariance(), delegate {
                                spawnMethod.Invoke(group, null);
                            }
                            );
                            _spawnClock.SetValue(group, spawnClock);
                            group.SpawnRepeating();
                            groupMatch = true;
                        }
                    }
                    if (!groupMatch) {
                        Dictionary <string, object> spawner = new Dictionary <string, object>();
                        spawner.Add("_refName", group.name);
                        spawner.Add("_refNumber", group.maxPopulation);
                        spawner.Add("delayMin", group.respawnDelayMin);
                        spawner.Add("delayMax", group.respawnDelayMax);
                        if (enableGroupTickData) {
                            spawner.Add("perTickMin", group.numToSpawnPerTickMin);
                            spawner.Add("perTickMax", group.numToSpawnPerTickMax);
                        }
                        (SpawnGroups[PrefabCut(monument.name)] as List<object>).Add(spawner);
                        addedGroup = true;
                    }
                }
            }
            if (addedMonument || addedGroup || addedTickData) {
                Config["Spawn", "Groups"] = SpawnGroups;
                Config.Save();
            }
            Puts($"Loaded '{SpawnGroups.Count()}' SpawnGroups");
        }
        void FixBarricades() {
            if (fixBarricadeStacking) return;
            var spawns = Resources.FindObjectsOfTypeAll<BaseEntity>().Where(c => c.isActiveAndEnabled && c.ShortPrefabName.StartsWith("door_barricade")).OrderBy(c => c.transform.position.x).ThenBy(c => c.transform.position.z).ThenBy(c => c.transform.position.z).ToList();
            var count = spawns.Count();
            var racelimit = count * count;
            var antirace = 0;
            var deleted = 0;
            for (var i = 0; i < count; i++) {
                var box = spawns[i];
                var next = i + 1;
                var pos = new Vector2(box.transform.position.x, box.transform.position.z);
                if (++antirace > racelimit) return;
                while (next < count) {
                    var box2 = spawns[next];
                    var pos2 = new Vector2(box2.transform.position.x, box2.transform.position.z);
                    var distance = Vector2.Distance(pos, pos2);
                    if (++antirace > racelimit) return;
                    if (distance < 0.5f) {
                        spawns.RemoveAt(next);
                        count--;
                        (box2 as BaseEntity).Kill();
                        deleted++;
                    }
                    else break;
                }
            }
            if (deleted > 0) Puts($"Removed {deleted} stacked DoorBarricades.");
        }
        void OnEntitySpawned(BaseNetworkable entity) {
            if (!_loaded || !fixBarricadeStacking || entity == null || !(entity as BaseEntity).ShortPrefabName.StartsWith("door_barricade")) return;
            NextTick(()=> {
                if (entity == null) return;
                BaseEntity[] stacked = null;
                try {
                    stacked = Physics.OverlapSphere(entity.transform.position, 0.5f).Where(entry => entry != null && entry.GetComponentInParent<BaseEntity>() != null && entry.GetComponentInParent<BaseEntity>().ShortPrefabName.StartsWith("door_barricade")).Select(entry => entry.GetComponentInParent<BaseEntity>()).Distinct().OrderByDescending(c => c.net.ID).ToArray();
                }
                catch {
                }
                if (stacked != null && stacked.Length > 1) for (int i = 0; i < stacked.Length - 1; i++) stacked[i].Kill();
            }
            );
        }
        [ConsoleCommand("sc.cleardata")]
        void ccmdClearData(ConsoleSystem.Arg arg) {
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            string data = string.Empty;
            if (arg.Args == null || arg.Args.Length < 1) {
                SendReply(arg, "You need to provide 'all','population' or 'groups'");
                return;
            }
            data = arg.Args[0];
            if (data == "all") {
                SpawnGroups.Clear();
                SpawnPopulation.Clear();
                Config["Spawn", "Groups"] = SpawnGroups;
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
                SendReply(arg, "Did reset all data.Next server boot loads the game defaults");
                return;
            }
            if (data == "population") {
                SpawnPopulation.Clear();
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
                SendReply(arg, "Did reset population data.Next server boot loads the game defaults");
                return;
            }
            if (data == "groups") {
                SpawnGroups.Clear();
                Config["Spawn", "Groups"] = SpawnGroups;
                Config.Save();
                SendReply(arg, "Did reset groups data.Next server boot loads the game defaults");
                return;
            }
            SendReply(arg, "You need to provide 'all','population' or 'groups'");
        }
        [ConsoleCommand("sc.tickinterval")]
        void ccmdTickInterval(ConsoleSystem.Arg arg) {
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            var _handler = SpawnHandler.Instance;
            float currTickInterval = _handler.TickInterval;
            if (arg.Args == null) {
                SendReply(arg, $"Current TickInterval is '{currTickInterval}' seconds");
                return;
            }
            if (arg.Args != null && arg.Args.Length >0) {
                float input = 0f;
                if (float.TryParse(arg.Args[0], out input)) {
                    currTickInterval = input;
                    SendReply(arg, $"TickInterval set to '{currTickInterval}' seconds");
                    _handler.StopCoroutine("SpawnTick");
                    _handler.TickInterval = currTickInterval;
                    _handler.StartCoroutine("SpawnTick");
                    if (currTickInterval != tickInterval) {
                        tickInterval = currTickInterval;
                        Config["Handler", "tickInterval"] = tickInterval;
                        Config.Save();
                    }
                    return;
                }
                else {
                    SendReply(arg, "You need to provide a full number in seconds");
                    return;
                }
            }
        }
        [ConsoleCommand("sc.fill")]
        void ccmdSpawnFill(ConsoleSystem.Arg arg) {
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            string populationname = string.Empty;
            bool single = false;
            if (arg.Args != null && arg.Args.Length >0) {
                populationname = arg.Args[0];
                single = true;
            }
            ServerMgr.Instance.StartCoroutine(SpawnFill(populationname, single, arg));
        }
        IEnumerator SpawnFill(string populationname, bool single, ConsoleSystem.Arg arg) {
            runningSpawnFill = true;
            yield return new WaitWhile(new System.Func<bool>(() => runningEnforceLimits));
            var _handler = SpawnHandler.Instance;
            _handler.StopCoroutine("SpawnTick");
            bool findany = false;
            if (single) {
                bool fullMatch = false;
                SpawnDistribution[] spawndists = (SpawnDistribution[])_SpawnDistributions.GetValue(_handler);
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        if ((_handler.SpawnPopulations[i].name.StartsWith(populationname) || _handler.SpawnPopulations[i].name.EndsWith(populationname)) && !fullMatch) {
                            if (_handler.SpawnPopulations[i].name == populationname) fullMatch = true;
                            int oldCount = _handler.GetCurrentCount(_handler.SpawnPopulations[i]);
                            _handler.SpawnInitial(_handler.SpawnPopulations[i], spawndists[i]);
                            if (arg.Args.Length > 1 && arg.Args[1] == "auto") if (logJobsToConsole) SendReply(arg, $"Timed population of '{_handler.SpawnPopulations[i].name}' | Old: {oldCount} | New: {_handler.GetCurrentCount(_handler.SpawnPopulations[i])}");
                            if (arg.Args.Length == 1) SendReply(arg, $"Forced population of '{_handler.SpawnPopulations[i].name}' | Old: {oldCount} | New: {_handler.GetCurrentCount(_handler.SpawnPopulations[i])}");
                            findany = true;
                            yield return new WaitForEndOfFrame();
                        }
                    }
                }
                if (!findany) SendReply(arg, $"SpawnPopulation '{populationname}' not found");
            }
            else {
                int oldCount = 0;
                int newCount = 0;
                SendReply(arg, "Filling All SpawnPopulations");
                SpawnDistribution[] spawndists = (SpawnDistribution[])_SpawnDistributions.GetValue(_handler);
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        oldCount += _handler.GetCurrentCount(_handler.SpawnPopulations[i]);
                        _handler.SpawnInitial(_handler.SpawnPopulations[i], spawndists[i]);
                        newCount += _handler.GetCurrentCount(_handler.SpawnPopulations[i]);
                        yield return new WaitForEndOfFrame();
                    }
                }
                SendReply(arg, $"Filled SpawnPopulations | Old: {oldCount} | New: {newCount}");
            }
            _handler.StartCoroutine("SpawnTick");
            runningSpawnFill = false;
            yield return null;
        }
        [ConsoleCommand("sc.raisedensity")]
        void ccmdSpawnRaiseDensity(ConsoleSystem.Arg arg) {
            var _handler = SpawnHandler.Instance;
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            float percentage = 0f;
            string populationname = string.Empty;
            if (arg.Args == null || arg.Args.Length < 2) {
                SendReply(arg, "You need to provide a number as percantage and a valid SpawnPopulation name");
                return;
            }
            float percent = -1;
            if (float.TryParse(arg.Args[0], out percent)) percentage = percent;
            else {
                SendReply(arg, "You need to provide a number as percentage");
                return;
            }
            if (percentage > 100f) {
                percentage = 100f;
                SendReply(arg, "Percentage was limited to 100% to avoid server freezes");
            }
            populationname = arg.Args[1];
            bool raiseAll = false;
            if (populationname == "all") raiseAll = true;
            SendReply(arg, $"Calling raise of density with '{percentage}' percent for '{populationname}'");
            ServerMgr.Instance.StartCoroutine(SpawnRaiseDensity(percentage, populationname, raiseAll, arg));
        }
        IEnumerator SpawnRaiseDensity(float percentage, string populationname, bool raiseAll, ConsoleSystem.Arg arg) {
            runningSpawnRaiseDensity = true;
            var _handler = SpawnHandler.Instance;
            _handler.StopCoroutine("SpawnTick");
            bool findany = false;
            if (!raiseAll) {
                bool fullMatch = false;
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        if ((_handler.SpawnPopulations[i].name.StartsWith(populationname) || _handler.SpawnPopulations[i].name.EndsWith(populationname)) && !fullMatch) {
                            if (_handler.SpawnPopulations[i].name == populationname) fullMatch = true;
                            float oldDensity = _handler.SpawnPopulations[i].TargetDensity;
                            float increaseDensity = 0f;
                            if (oldDensity > 0f) increaseDensity = _handler.SpawnPopulations[i].TargetDensity / 100 * percentage;
                            else {
                                object backupDensity = null;
                                if (spawnDefaults.TryGetValue(_handler.SpawnPopulations[i].name, out backupDensity)) increaseDensity = Convert.ToSingle(backupDensity) / 100 * percentage;
                                else increaseDensity = _handler.SpawnPopulations[i].TargetDensity / 100 * percentage;
                            }
                            float newDensity = (float)Math.Round((double)(oldDensity+increaseDensity));
                            _targetDensity.SetValue(_handler.SpawnPopulations[i], newDensity);
                            (SpawnPopulation[_handler.SpawnPopulations[i].name] as Dictionary<string, object>)["spawndensity"] = _handler.SpawnPopulations[i].TargetDensity;
                            SendReply(arg, $"Raised density of '{_handler.SpawnPopulations[i].name}' | Old: {oldDensity} | New: {newDensity}");
                            findany = true;
                        }
                    }
                }
                if (!findany) SendReply(arg, $"SpawnPopulation '{populationname}' not found");
                else {
                    SendReply(arg, "New raised density's set and saved.");
                    Config["Spawn", "Population"] = SpawnPopulation;
                    Config.Save();
                    string type = arg.Args[1];
                    arg.Args = new string[] {
                        type
                    }
                    ;
                    NextTick(() => ccmdSpawnFill(arg));
                }
            }
            else {
                SendReply(arg, $"Raising all SpawnPopulation density's by '{percentage}' percent");
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        float oldDensity = _handler.SpawnPopulations[i].TargetDensity;
                        float increaseDensity = _handler.SpawnPopulations[i].TargetDensity / 100 * percentage;
                        float newDensity = (float)Math.Round((double)(oldDensity+increaseDensity));
                        _targetDensity.SetValue(_handler.SpawnPopulations[i], newDensity);
                        (SpawnPopulation[_handler.SpawnPopulations[i].name] as Dictionary<string, object>)["spawndensity"] = _handler.SpawnPopulations[i].TargetDensity;
                    }
                }
                SendReply(arg, "New raised density's set and saved.");
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
                arg.Args = null;
                NextTick(() => ccmdSpawnFill(arg));
            }
            _handler.StartCoroutine("SpawnTick");
            runningSpawnRaiseDensity = false;
            yield return null;
        }
        [ConsoleCommand("sc.lowerdensity")]
        void ccmdSpawnLowerDensity(ConsoleSystem.Arg arg) {
            var _handler = SpawnHandler.Instance;
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            float percentage = 0f;
            string populationname = string.Empty;
            if (arg.Args == null || arg.Args.Length < 2) {
                SendReply(arg, "You need to provide a percentage number and a valid SpawnPopulation name");
                return;
            }
            float percent = -1;
            if (float.TryParse(arg.Args[0], out percent)) percentage = percent;
            else {
                SendReply(arg, "You need to provide a number as percentage");
                return;
            }
            populationname = arg.Args[1];
            bool lowerAll = false;
            if (populationname == "all") lowerAll = true;
            if (percentage > 100f) {
                percentage = 100f;
                SendReply(arg, "Percentage was limited to 100%");
            }
            bool force = false;
            if (arg.Args.Length >= 3 && arg.Args[2] == "force") force = true;
            if (lowerAll && percentage == 100f && !force) {
                SendReply(arg, "Canceled: Lowering all by 100% would set all to zero pop");
                SendReply(arg, "You need to add 'force' as additional argument!");
                return;
            }
            SendReply(arg, $"Calling lower with '{percentage}' percent for '{populationname}'");
            ServerMgr.Instance.StartCoroutine(SpawnLowerDensity(percentage, populationname, lowerAll, arg));
        }
        IEnumerator SpawnLowerDensity(float percentage, string populationname, bool lowerAll, ConsoleSystem.Arg arg) {
            runningSpawnLowerDensity = true;
            var _handler = SpawnHandler.Instance;
            _handler.StopCoroutine("SpawnTick");
            bool findany = false;
            if (!lowerAll) {
                bool fullMatch = false;
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        if ((_handler.SpawnPopulations[i].name.StartsWith(populationname) || _handler.SpawnPopulations[i].name.EndsWith(populationname)) && !fullMatch) {
                            if (_handler.SpawnPopulations[i].name == populationname) fullMatch = true;
                            float oldDensity = _handler.SpawnPopulations[i].TargetDensity;
                            float decreaseDensity = _handler.SpawnPopulations[i].TargetDensity / 100 * percentage;
                            float newDensity = -1f;
                            if (percentage == 100f) newDensity = 0f;
                            else newDensity = (float)Math.Round((double)(oldDensity-decreaseDensity));
                            _targetDensity.SetValue(_handler.SpawnPopulations[i], newDensity);
                            (SpawnPopulation[_handler.SpawnPopulations[i].name] as Dictionary<string, object>)["spawndensity"] = _handler.SpawnPopulations[i].TargetDensity;
                            SendReply(arg, $"Lowered density of '{_handler.SpawnPopulations[i].name}' | Old: {oldDensity} | New: {newDensity}");
                            findany = true;
                        }
                    }
                }
                if (!findany) SendReply(arg, $"SpawnPopulation '{populationname}' not found");
                else {
                    SendReply(arg, $"New lowered density's set and saved.");
                    Config["Spawn", "Population"] = SpawnPopulation;
                    Config.Save();
                    NextTick(() => ccmdEnforceLimits(arg));
                }
            }
            else {
                SendReply(arg, $"Lowering all SpawnPopulation density's by '{percentage}' percent");
                for (int i = 0; i < _handler.SpawnPopulations.Length; i++) {
                    if (!(_handler.SpawnPopulations[i] == null)) {
                        float oldDensity = _handler.SpawnPopulations[i].TargetDensity;
                        float decreaseDensity = _handler.SpawnPopulations[i].TargetDensity / 100 * percentage;
                        float newDensity = -1f;
                        if (percentage == 100f) newDensity = 0f;
                        else newDensity = (float)Math.Round((double)(oldDensity-decreaseDensity));
                        _targetDensity.SetValue(_handler.SpawnPopulations[i], newDensity);
                        (SpawnPopulation[_handler.SpawnPopulations[i].name] as Dictionary<string, object>)["spawndensity"] = _handler.SpawnPopulations[i].TargetDensity;
                    }
                }
                SendReply(arg, $"New lowered density's set and saved");
                Config["Spawn", "Population"] = SpawnPopulation;
                Config.Save();
                NextTick(() => ccmdEnforceLimits(arg));
            }
            _handler.StartCoroutine("SpawnTick");
            runningSpawnLowerDensity = false;
            yield return null;
        }
        [ConsoleCommand("sc.kill")]
        void ccmdSpawnKill(ConsoleSystem.Arg arg) {
            var _handler = SpawnHandler.Instance;
            if(arg.Connection != null && arg.Connection.authLevel < 2) return;
            string populationname = string.Empty;
            if (arg.Args == null || arg.Args.Length < 1) {
                SendReply(arg, $"You need to provide a valid SpawnPopulation name");
                return;
            }
            populationname = arg.Args[0];
            bool killAll = false;
            if (populationname == "all") killAll = true;
            SendReply(arg, $"Calling kill for '{populationname}'");
            ServerMgr.Instance.StartCoroutine(SpawnKill(populationname, killAll, arg));
        }
        IEnumerator SpawnKill(string populationname, bool killAll, ConsoleSystem.Arg arg) {
            runningSpawnKill = true;
            var _handler = SpawnHandler.Instance;
            _handler.StopCoroutine("SpawnTick");
            bool findany = false;
            SpawnPopulation[] spawnpops = _handler.SpawnPopulations.ToArray();
            int countDeleted = 0;
            bool fullMatch = false;
            bool junkPiles = false;
            for (int i = 0; i < spawnpops.Length; i++) {
                if (!(spawnpops[i] == null)) {
                    if ((spawnpops[i].name.StartsWith(populationname) || (spawnpops[i].name.EndsWith(populationname)) && !fullMatch) || killAll) {
                        if (spawnpops[i].name == populationname) fullMatch = true;
                        Spawnable[] array = _handler.FindAll(spawnpops[i]);
                        int count = array.Length;
                        foreach (Spawnable current in array) {
                            BaseEntity baseEntity = current.gameObject.ToBaseEntity();
                            if (baseEntity.IsValid()) {
                                if (baseEntity is JunkPile) {
                                    (baseEntity as JunkPile).SinkAndDestroy();
                                    junkPiles = true;
                                }
                                else baseEntity.Kill(BaseNetworkable.DestroyMode.None);
                                countDeleted++;
                            }
                            else {
                                GameManager.Destroy(current.gameObject, 0f);
                                countDeleted++;
                            }
                        }
                        if (!killAll) {
                            if (junkPiles) SendReply(arg, $"Forced deletion of '{spawnpops[i].name}' | Old: {count} | New: {_handler.GetCurrentCount
// ... [Code preview truncated due to length. Full source in attached file] ...

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