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

FREE RaidableBases : 2.6.6 2.6.6

Нет прав для скачивания
C#:
#pragma warning disable
using Facepunch;
using Facepunch.Math;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using Oxide.Game.Rust.Cui;
using Oxide.Game.Rust.Libraries;
using Oxide.Plugins.RaidableBasesExtensionMethods;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
namespace Oxide.Plugins {
    [Info("Raidable Bases", "nivex", "2.6.6")]
    [Description("Create fully automated raidable bases with npcs.")]
    class RaidableBases : RustPlugin {
        [PluginReference]
        private Plugin DangerousTreasures, ZoneManager, IQEconomic, Economics, ServerRewards, GUIAnnouncements, AdvancedAlerts, Archery, Friends, Clans, Kits, TruePVE, NightLantern, Wizardry, NextGenPVE, Imperium, Backpacks, BaseRepair, Notify, SkillTree;
        private new const string Name = "RaidableBases";
        private const int targetMask = Layers.Mask.World | Layers.Mask.Terrain | Layers.Mask.Default;
        private const int visibleMask = Layers.Mask.Deployed | Layers.Mask.Construction | targetMask;
        private const int targetMask2 = Layers.Mask.Construction | Layers.Mask.Water | targetMask;
        private const int manualMask = Layers.Mask.Deployed | Layers.Mask.Tree | targetMask2;
        private const int blockLayers = Layers.Mask.Construction | Layers.Mask.Deployed | Layers.Mask.Player_Server;
        private static RaidableBases Instance {
            get;
            set;
        }
        private ScheduledController Scheduled {
            get;
            set;
        }
        private MaintainedController Maintained {
            get;
            set;
        }
        private QueueController Queues {
            get;
            set;
        }
        private Coroutine setupCopyPasteObstructionRadius {
            get;
            set;
        }
        private float OceanLevel {
            get;
            set;
        }
        private RotationCycle Cycle {
            get;
            set;
        }
        = new RotationCycle();
        public List<RaidableBase> Raids {
            get;
        }
        = new List<RaidableBase>();
        public Dictionary<ulong, DelaySettings> PvpDelay {
            get;
        }
        = new Dictionary<ulong, DelaySettings>();
        public Dictionary<ulong, HumanoidBrain> HumanoidBrains {
            get;
            set;
        }
        = new Dictionary<ulong, HumanoidBrain>();
        private Dictionary<string, SkinInfo> Skins {
            get;
        }
        = new Dictionary<string, SkinInfo>();
        private Dictionary<uint, BMGELEVATOR> _elevators {
            get;
            set;
        }
        = new Dictionary<uint, BMGELEVATOR>();
        public static StoredData data {
            get;
            set;
        }
        = new StoredData();
        public TemporaryData temporaryData {
            get;
            set;
        }
        = new TemporaryData();
        private static StringBuilder _sb {
            get;
            set;
        }
        private static StringBuilder _sb2 {
            get;
            set;
        }
        private bool wiped {
            get;
            set;
        }
        private bool buyableEnabled {
            get;
            set;
        }
        private float lastSpawnRequestTime {
            get;
            set;
        }
        private bool IsUnloading {
            get;
            set;
        }
        private bool IsShuttingDown {
            get;
            set;
        }
        private bool bypassRestarting {
            get;
            set;
        }
        private BuildingTables Buildings {
            get;
            set;
        }
        private bool DebugMode {
            get;
            set;
        }
        private int despawnLimit {
            get;
            set;
        }
        = 10;
        private Dictionary<string, ItemDefinition> _deployables {
            get;
            set;
        }
        = new Dictionary<string, ItemDefinition>();
        private Dictionary<ItemDefinition, string> _definitions {
            get;
            set;
        }
        = new Dictionary<ItemDefinition, string>();
        private List<uint> ExcludedMounts {
            get;
            set;
        }
        = new List<uint> {
            3552983236, 4218596772, 1845856065, 1992774774, 629849447, 4267988016, 1418740895, 2493676858, 3814928951, 1980628900, 703403829, 3061223907, 113644298, 3691382632, 3858860623, 286221745, 2230162530, 51176708, 3363531184, 3224878175
        }
        ;
        private List<string> Blocks {
            get;
            set;
        }
        = new List<string> {
            "wall.doorway", "wall", "wall.frame", "wall.half", "wall.low", "wall.window", "foundation.triangle", "foundation", "wall.external.high.wood", "wall.external.high.stone", "wall.external.high.ice", "floor.triangle.frame", "floor.triangle", "floor.frame"
        }
        ;
        private List<string> TrueDamage {
            get;
            set;
        }
        = new List<string> {
            "spikes.floor", "barricade.metal", "barricade.woodwire", "barricade.wood", "wall.external.high.wood", "wall.external.high.stone", "wall.external.high.ice"
        }
        ;
        private List<string> arguments {
            get;
            set;
        }
        = new List<string> {
            "add", "remove", "list", "clean", "easy", "med", "medium", "hard", "expert", "nightmare", "0", "1", "2", "3", "4", "maintained", "scheduled", "buyable", "toggle"
        }
        ;
        private List<string> unityEngineScripts {
            get;
            set;
        }
        = new List<string> {
            "saddletest", "fuel_storage"
        }
        ;
        private SkinSettingsImportedWorkshop ImportedWorkshopSkins {
            get;
            set;
        }
        private List<string> _lockoutKeys = new List<string>();
        private const float M_RADIUS = 25f;
        private const float CELL_SIZE = M_RADIUS / 2f;
        private List<PasteLoadInfo> loadCoroutines = new List<PasteLoadInfo>();
        private static Dictionary<string, PasteData> _pasteData = new Dictionary<string, PasteData>();
        private readonly IPlayer _consolePlayer = new Game.Rust.Libraries.Covalence.RustConsolePlayer();
        private List<BaseEntity.Slot> _checkSlots = new List<BaseEntity.Slot> {
            BaseEntity.Slot.Lock, BaseEntity.Slot.UpperModifier, BaseEntity.Slot.MiddleModifier, BaseEntity.Slot.LowerModifier
        }
        ;
        public class PasteData {
            public bool valid;
            public float radius;
            public List<Vector3> foundations;
            public PasteData() {
            }
            public static PasteData Get(string baseName) {
                PasteData pasteData;
                if (!_pasteData.TryGetValue(baseName, out pasteData)) {
                    _pasteData[baseName] = pasteData = new PasteData();
                }
                return pasteData;
            }
        }
        public class PasteLoadInfo {
            public Coroutine coroutine;
            public RandomBase rb;
            public PasteLoadInfo(Coroutine coroutine, RandomBase rb) {
                this.coroutine = coroutine;
                this.rb = rb;
            }
        }
        private List<RankedRecord> RankedRecords = new List<RankedRecord> {
            new RankedRecord("raidablebases.ladder.easy", "raideasy", RaidableMode.Easy), new RankedRecord("raidablebases.ladder.medium", "raidmedium", RaidableMode.Medium), new RankedRecord("raidablebases.ladder.hard", "raidhard", RaidableMode.Hard), new RankedRecord("raidablebases.ladder.expert", "raidexpert", RaidableMode.Expert), new RankedRecord("raidablebases.ladder.nightmare", "raidnightmare", RaidableMode.Nightmare), new RankedRecord("raidablebases.th", "raidhunter", RaidableMode.Points),
        }
        ;
        public enum EjectCode {
            Awaken, Banned, Enter, Exceeds, FauxAdmin, Hogging, Lockout, Mounted, Protector, Scavenging, Sleeper, Spawning, Teleported, None
        }
        public enum RaidableType {
            None, Manual, Scheduled, Purchased, Maintained, Grid
        }
        public enum RaidableMode {
            Disabled = -1, Easy = 0, Medium = 1, Hard = 2, Expert = 3, Nightmare = 4, Points = 8888, Random = 9999
        }
        public enum AlliedType {
            All, Clan, Friend, Team
        }
        public enum CacheType {
            Close, Delete, Generic, Temporary, Privilege, Seabed, Submerged
        }
        public enum ConstructionType {
            Barricade, Ladder, Any
        }
        public enum SpawnResult {
            Failure, Transfer, Success, Skipped
        }
        public class TemporaryData {
            public List<uint> UID {
                get;
                set;
            }
            = new List<uint>();
            public TemporaryData() {
            }
            public void CleanupTemporaryFiles(List<uint> uids) {
                var entities = new List<BaseEntity>();
                foreach (uint uid in uids) {
                    var entity = BaseNetworkable.serverEntities.Find(uid) as BaseEntity;
                    if (entity.IsKilled()) UID.Remove(uid);
                    else entities.Add(entity);
                }
                if (entities.Count > 0) {
                    Instance.UndoLoop(entities, 10, true, false, true);
                }
                Instance.SaveTemporaryData();
            }
        }
        public class StoredData {
            [JsonProperty(PropertyName = "PlayerLockouts")]
            public Dictionary<string, Lockout> Lockouts {
                get;
            }
            = new Dictionary<string, Lockout>();
            public Dictionary<string, PlayerInfo> Players {
                get;
                set;
            }
            = new Dictionary<string, PlayerInfo>();
            public Dictionary<ulong, BuyableInfo> BuyableCooldowns {
                get;
                set;
            }
            = new Dictionary<ulong, BuyableInfo>();
            public string RaidTime {
                get;
                set;
            }
            = DateTime.MinValue.ToString();
            public int TotalEvents {
                get;
                set;
            }
            public StoredData() {
            }
        }
        public class SpawnComparer : IComparer<RaidableSpawnLocation> {
            private Vector3 a;
            public SpawnComparer(Vector3 a) {
                this.a = a;
            }
            int IComparer<RaidableSpawnLocation>.Compare(RaidableSpawnLocation x, RaidableSpawnLocation y) {
                return (x.Location - a).sqrMagnitude.CompareTo((y.Location - a).sqrMagnitude);
            }
        }
        public class RandomBase {
            public ulong userid;
            public IPlayer user;
            public BasePlayer owner;
            public PasteData pasteData;
            public string BaseName;
            public Vector3 Position;
            public BaseProfile Profile;
            public RaidableType type;
            public RaidableSpawns spawns;
            public Payments payments;
            public float Radius;
            public float loadTime;
            public float heightAdj;
            public float typeDistance;
            public float protectionRadius;
            public float safeRadius;
            public float buildRadius;
            public int attempts;
            public bool autoHeight;
            public bool stability;
            public bool checkTerrain;
            public bool Sorted;
            public bool IsUnloading;
            public RandomBase() {
            }
            public RandomBase(string BaseName, BaseProfile Profile, Vector3 Position, RaidableType Type, RaidableSpawns spawns, Payments payments) {
                this.BaseName = BaseName;
                this.Position = Position;
                this.Profile = Profile;
                this.type = Type;
                this.spawns = spawns;
                this.payments = payments;
                this.Radius = Profile.Options.ProtectionRadius(Type);
            }
            public BuildingOptions options => Profile.Options;
            public bool isBuyableEvent => payments != null && payments.position != Vector3.zero;
            public bool hasSpawns => spawns.Spawns.Count > 0 || spawns.Seabed.Count > 0 && options.Water.SpawnOnSeabed;
            public void TrySortByDistance() {
                if (!Sorted && isBuyableEvent && config.Settings.Buyable.Closest) {
                    Message(owner, "BuyBaseLocate");
                    var positions = spawns.GetLocations(options.Water.CacheType).ToList();
                    positions.Sort(new SpawnComparer(payments.position));
                    if (options.Water.CacheType == CacheType.Seabed) {
                        spawns.Seabed = new HashSet<RaidableSpawnLocation>(positions);
                    }
                    else spawns.Spawns = new HashSet<RaidableSpawnLocation>(positions);
                    Sorted = true;
                }
                else Sorted = false;
            }
        }
        public class BackpackData {
            public DroppedItemContainer backpack;
            public BasePlayer player;
            public ulong userID;
        }
        public class BuyableInfo {
            public string Easy, Medium, Hard, Expert, Nightmare;
            private static double GetTimeRemaining(ulong userid, RaidableMode mode) {
                var diff = mode == RaidableMode.Easy ? config.Settings.Buyable.Cooldowns.Easy : mode == RaidableMode.Medium ? config.Settings.Buyable.Cooldowns.Medium : mode == RaidableMode.Hard ? config.Settings.Buyable.Cooldowns.Hard : mode == RaidableMode.Expert ? config.Settings.Buyable.Cooldowns.Expert : config.Settings.Buyable.Cooldowns.Nightmare;
                if (diff.Cooldown <= 0) return 0;
                BuyableInfo bi;
                if (!data.BuyableCooldowns.TryGetValue(userid, out bi)) return 0f;
                var dateString = mode == RaidableMode.Easy ? bi.Easy : mode == RaidableMode.Medium ? bi.Medium : mode == RaidableMode.Hard ? bi.Hard : mode == RaidableMode.Expert ? bi.Expert : bi.Nightmare;
                DateTime date;
                if (!DateTime.TryParse(dateString, out date)) return 0;
                double time = date.Subtract(DateTime.Now).TotalSeconds;
                return time > 0 ? time : 0;
            }
            public static double GetTimeRemaining(BasePlayer buyer, RaidableMode mode) {
                double time = GetTimeRemaining(buyer.userID, mode);
                if (time > 0) {
                    Message(buyer, "BuyCooldown", Math.Ceiling(time));
                    return time;
                }
                return 0;
            }
            public static double GetTimeRemaining(ulong userid) {
                foreach (RaidableMode mode in GetRaidableModes()) {
                    double time = GetTimeRemaining(userid, mode);
                    if (time > 0) {
                        return time;
                    }
                }
                data.BuyableCooldowns.Remove(userid);
                return 0;
            }
        }
        public class DelaySettings {
            public RaidableBase RaidableBase;
            public Timer Timer;
            public bool AllowPVP;
            public float time;
        }
        public class MountInfo {
            public Vector3 position;
            public float radius;
            public BaseMountable mountable;
        }
        public class SkinInfo {
            public List<ulong> skins = new List<ulong>();
            public List<ulong> workshopSkins = new List<ulong>();
            public List<ulong> importedSkins = new List<ulong>();
            public List<ulong> allSkins = new List<ulong>();
        }
        public class Lockout {
            public double Easy, Medium, Hard, Expert, Nightmare;
            public bool Any() => Easy > 0 || Medium > 0 || Hard > 0 || Expert > 0 || Nightmare > 0;
        }
        public class RankedRecord {
            public string Permission;
            public string Group;
            public RaidableMode Mode;
            public RankedRecord(string permission, string group, RaidableMode mode) {
                Permission = permission;
                Group = group;
                Mode = mode;
            }
        }
        public class LandLevel {
            public float Min;
            public float Max;
        }
        public class RaidableSpawnLocation {
            public List<Vector3> Surroundings = new List<Vector3>();
            public Vector3 Location = Vector3.zero;
            public float WaterHeight;
            public float TerrainHeight;
            public float SpawnHeight;
            public float Radius;
            public bool AutoHeight;
            public RaidableSpawnLocation(Vector3 Location) {
                this.Location = Location;
            }
        }
        public class ZoneInfo {
            public Vector3 Position;
            public Vector3 Size;
            public float Distance;
            public OBB OBB;
            public ZoneInfo(object location, object radius, object size) {
                Position = (Vector3)location;
                if (radius is float) {
                    Distance = (float)radius + M_RADIUS + config.Settings.ZoneDistance;
                }
                if (size is Vector3) {
                    Size = (Vector3)size;
                }
                var bounds = new Bounds(Position, Size);
                if (config.Settings.ZoneDistance > 0f) {
                    bounds.Expand(config.Settings.ZoneDistance);
                }
                OBB = new OBB(Position, default(Quaternion), bounds);
            }
        }
        public class BaseProfile {
            public List<LootItem> BaseLootList {
                get;
                set;
            }
            = new List<LootItem>();
            public BuildingOptions Options {
                get;
                set;
            }
            = new BuildingOptions();
            public RaidableSpawns Spawns {
                get;
                set;
            }
            = new RaidableSpawns();
            public string ProfileName {
                get;
                set;
            }
            public BaseProfile() {
                Options.AdditionalBases = new Dictionary<string, List<PasteOption>>();
            }
            public BaseProfile(BuildingOptions options, string name) {
                Options = options;
                ProfileName = name;
            }
            public static BaseProfile Clone(BaseProfile profile) {
                return profile.MemberwiseClone() as BaseProfile;
            }
        }
        private class BuildingTables {
            public Dictionary<RaidableMode, List<LootItem>> DifficultyLootLists {
                get;
                set;
            }
            = new Dictionary<RaidableMode, List<LootItem>>();
            public Dictionary<DayOfWeek, List<LootItem>> WeekdayLootLists {
                get;
                set;
            }
            = new Dictionary<DayOfWeek, List<LootItem>>();
            public Dictionary<string, BaseProfile> Profiles {
                get;
                set;
            }
            = new Dictionary<string, BaseProfile>();
            public bool IsConfigured(string baseName) => Profiles.Exists(m => m.Key == baseName || m.Value.Options.AdditionalBases.ContainsKey(baseName));
        }
        public static class GridController {
            internal static Dictionary<RaidableType, RaidableSpawns> Spawns {
                get;
                set;
            }
            = new Dictionary<RaidableType, RaidableSpawns>();
            internal static Coroutine gridCoroutine {
                get;
                set;
            }
            internal static Coroutine fileCoroutine {
                get;
                set;
            }
            internal static float gridTime {
                get;
                set;
            }
            public static void Clear() {
                foreach (RaidableType type in Enum.GetValues(typeof(RaidableType))) {
                    RaidableSpawns rs;
                    if (Spawns.TryGetValue(type, out rs)) {
                        rs.Seabed.Clear();
                        rs.Spawns.Clear();
                        rs.Cached.Clear();
                    }
                }
                Spawns.Clear();
            }
            public static double GetRaidTime() => DateTime.Parse(data.RaidTime).Subtract(DateTime.Now).TotalSeconds;
            public static void StartAutomation() {
                if (Instance.Scheduled.Enabled) {
                    if (data.RaidTime != DateTime.MinValue.ToString() && GetRaidTime() > config.Settings.Schedule.IntervalMax) {
                        data.RaidTime = DateTime.MinValue.ToString();
                    }
                    Instance.Scheduled.StartCoroutine();
                }
                if (Instance.Maintained.Enabled) {
                    Instance.Maintained.StartCoroutine();
                }
            }
            private static IEnumerator LoadFiles() {
                yield return Instance.LoadTables();
                yield return Instance.LoadProfiles();
                yield return CoroutineEx.waitForSeconds(5f);
                RaidableBase.IsSpawnerBusy = false;
                StartAutomation();
            }
            public static void Setup() {
                if (Spawns.Count >= 5) {
                    fileCoroutine = ServerMgr.Instance.StartCoroutine(LoadFiles());
                    return;
                }
                StopCoroutine();
                gridCoroutine = ServerMgr.Instance.StartCoroutine(GenerateGrid());
            }
            public static void StopCoroutine() {
                if (gridCoroutine != null) {
                    ServerMgr.Instance.StopCoroutine(gridCoroutine);
                    gridCoroutine = null;
                }
                if (fileCoroutine != null) {
                    ServerMgr.Instance.StopCoroutine(fileCoroutine);
                    fileCoroutine = null;
                }
            }
            private static IEnumerator GenerateGrid()  // Credits to Jake_Rich for helping me with this!
            {
                yield return CoroutineEx.waitForSeconds(0.1f);
                while (Performance.report.frameRate < 15 && ConVar.FPS.limit > 15) {
                    yield return CoroutineEx.waitForSeconds(1f);
                }
                var gridStopwatch = Stopwatch.StartNew();
                RaidableSpawns spawns = Spawns[RaidableType.Grid] = new RaidableSpawns();
                gridTime = Time.realtimeSinceStartup;
                yield return Instance.LoadTables();
                yield return Instance.LoadProfiles();
                yield return SpawnsController.SetupMonuments();
                bool spawnOnSeabed = false;
                int minPos = (int)(World.Size / -2f);
                int maxPos = (int)(World.Size / 2f);
                float maxProtectionRadius = -10000f;
                float minProtectionRadius = 10000f;
                float maxWaterDepthSeabed = 0f;
                float minWaterDepthSeabed = 0f;
                float maxWaterDepth = 0f;
                float landLevel = 0.5f;
                int checks = 0;
                foreach (var profile in Instance.Buildings.Profiles.Values) {
                    if (profile.Options.Water.Seabed > 0f) spawnOnSeabed = true;
                    maxProtectionRadius = Mathf.Max(profile.Options.ProtectionRadii.Max(), maxProtectionRadius);
                    minProtectionRadius = Mathf.Min(profile.Options.ProtectionRadii.Min(), minProtectionRadius);
                    maxWaterDepthSeabed = Mathf.Min(maxWaterDepthSeabed, profile.Options.Water.MaximumSeabedWaterDepth);
                    minWaterDepthSeabed = Mathf.Min(minWaterDepthSeabed, profile.Options.Water.MinimumSeabedWaterDepth);
                    maxWaterDepth = Mathf.Max(maxWaterDepth, profile.Options.Water.WaterDepth);
                    landLevel = Mathf.Max(Mathf.Clamp(profile.Options.LandLevel, 0.5f, 3f), landLevel);
                }
                if (!config.Settings.Management.AllowOnBeach && !config.Settings.Management.AllowInland && !spawnOnSeabed) {
                    Puts("Grid has failed initialization.Your configuration does not have any spawn options for beaches, inland or seabed enabled!");
                    gridCoroutine = null;
                    gridStopwatch.Stop();
                    yield break;
                }
                float zeroDist = Mathf.Clamp(config.Settings.Management.Vector3ZeroDistance, 0f, World.Size / 2f);
                for (float x = minPos; x < maxPos; x += CELL_SIZE) {
                    for (float z = minPos; z < maxPos; z += CELL_SIZE) {
                        var position = new Vector3(x, 0f, z);
                        if (InRange(position, Vector3.zero, zeroDist)) {
                            continue;
                        }
                        position.y = SpawnsController.GetSpawnHeight(position);
                        SpawnsController.ExtractLocation(spawns, position, landLevel, minProtectionRadius, maxProtectionRadius, minWaterDepthSeabed, maxWaterDepthSeabed, maxWaterDepth, spawnOnSeabed);
                        if (++checks >= 25) {
                            checks = 0;
                            yield return CoroutineEx.waitForSeconds(0.0035f);
                        }
                    }
                }
                RaidableBase.IsSpawnerBusy = false;
                GridController.StartAutomation();
                Instance.Queues.Messages.Clear();
                gridStopwatch.Stop();
                gridCoroutine = null;
                Puts(mx("Initialized Grid", null, Math.Floor(gridStopwatch.Elapsed.TotalSeconds), gridStopwatch.Elapsed.Milliseconds, World.Size, spawns.Spawns.Count));
                if (spawns.Seabed.Count > 0) Puts(mx("Initialized Grid Sea", null, spawns.Seabed.Count));
            }
            public static void LoadSpawns() {
                Clear();
                Spawns.Add(RaidableType.Grid, new RaidableSpawns());
                if (SpawnsFileValid(config.Settings.Manual.SpawnsFile)) {
                    var spawns = GetSpawnsLocations(config.Settings.Manual.SpawnsFile);
                    if (spawns?.Count > 0) {
                        Puts(mx("LoadedManual", null, spawns.Count));
                        Spawns[RaidableType.Manual] = new RaidableSpawns(spawns);
                    }
                }
                if (SpawnsFileValid(config.Settings.Schedule.SpawnsFile)) {
                    var spawns = GetSpawnsLocations(config.Settings.Schedule.SpawnsFile);
                    if (spawns?.Count > 0) {
                        Puts(mx("LoadedScheduled", null, spawns.Count));
                        Spawns[RaidableType.Scheduled] = new RaidableSpawns(spawns);
                    }
                }
                if (SpawnsFileValid(config.Settings.Maintained.SpawnsFile)) {
                    var spawns = GetSpawnsLocations(config.Settings.Maintained.SpawnsFile);
                    if (spawns?.Count > 0) {
                        Puts(mx("LoadedMaintained", null, spawns.Count));
                        Spawns[RaidableType.Maintained] = new RaidableSpawns(spawns);
                    }
                }
                if (SpawnsFileValid(config.Settings.Buyable.SpawnsFile)) {
                    var spawns = GetSpawnsLocations(config.Settings.Buyable.SpawnsFile);
                    if (spawns?.Count > 0) {
                        Puts(mx("LoadedBuyable", null, spawns.Count));
                        Spawns[RaidableType.Purchased] = new RaidableSpawns(spawns);
                    }
                }
            }
            public static bool SpawnsFileValid(string spawnsFile) {
                if (string.IsNullOrEmpty(spawnsFile) || spawnsFile.Equals("none", StringComparison.OrdinalIgnoreCase)) {
                    return false;
                }
                return FileExists($"SpawnsDatabase{Path.DirectorySeparatorChar}{spawnsFile}");
            }
            public static HashSet<RaidableSpawnLocation> GetSpawnsLocations(string spawnsFile) {
                Spawnfile data;
                try {
                    data = Interface.Oxide.DataFileSystem.ReadObject<Spawnfile>($"SpawnsDatabase{Path.DirectorySeparatorChar}{spawnsFile}");
                }
                catch (JsonReaderException) {
                    return null;
                }
                var locations = new HashSet<RaidableSpawnLocation>();
                if (data == null) {
                    return locations;
                }
                foreach (var element in data.spawnPoints) {
                    if (element.Value == null) continue;
                    var value = element.Value.ToString();
                    if (string.IsNullOrEmpty(value)) continue;
                    var vector = value.ToVector3();
                    if (vector == Vector3.zero) continue;
                    locations.Add(new RaidableSpawnLocation(vector));
                }
                return locations;
            }
        }
        private class Spawnfile {
            public Dictionary<string, object> spawnPoints = new Dictionary<string, object>();
        }
        public class QueueController {
            internal const float spawnDelay = 0.1f;
            internal const float pauseDelay = 1.0f;
            internal const int elementLimit = 20;
            internal const int valueLimit = 5;
            internal int spawnChecks;
            internal bool Paused;
            internal Coroutine _coroutine;
            internal bool Any => queue.Count > 0;
            internal Queue<RandomBase> queue = new Queue<RandomBase>();
            internal const int layers = Layers.Mask.Player_Server | Layers.Mask.Construction | Layers.Mask.Deployed | Layers.Mask.Ragdoll;
            internal DebugMessages Messages = new DebugMessages();
            public class DebugMessages {
                public class Info {
                    public int amount = 1;
                    public List<string> values = new List<string>();
                    public override string ToString() {
                        if (values.Count > 0) {
                            return $": {string.Join(", ", values.ToArray())}";
                        }
                        return string.Empty;
                    }
                }
                internal Dictionary<string, Info> _elements = new Dictionary<string, Info>();
                internal IPlayer DebugUser;
                public string Add(string element, object obj = null) {
                    if (string.IsNullOrEmpty(element)) {
                        return null;
                    }
                    Info info;
                    if (!_elements.TryGetValue(element, out info)) {
                        if (elementLimit > 0 && _elements.Count >= elementLimit) {
                            _elements.Remove(_elements.ElementAt(0).Key);
                        }
                        _elements[element] = info = new Info();
                    }
                    else info.amount++;
                    if (obj == null) {
                        return element;
                    }
                    string value = obj.ToString().Replace("(", "").Replace(")", "").Replace(",", "");
                    if (!info.values.Contains(value)) {
                        if (valueLimit > 0 && info.values.Count >= valueLimit) {
                            info.values.RemoveAt(0);
                        }
                        info.values.Add(value);
                    }
                    return $"{element}: {value}";
                }
                public void Clear() {
                    _elements.Clear();
                }
                public bool Any() {
                    return _elements.Count > 0;
                }
                public void PrintAll(IPlayer user = null) {
                    if (_elements.Count > 0 && IsInstanceValid && Instance.DebugMode) {
                        foreach (var element in _elements) {
                            PrintInternal(user, $"{element.Value.amount}x - {element.Key}{element.Value.ToString()}");
                        }
                        Clear();
                    }
                }
                private bool PrintInternal(IPlayer user, string message) {
                    if (!string.IsNullOrEmpty(message) && IsInstanceValid && Instance.DebugMode) {
                        if (config.LogToFile) {
                            Instance.LogToFile("debug", message, Instance, true);
                        }
                        if (user == null) {
                            Puts("DEBUG: {0}", message);
                        }
                        else user.Reply($"DEBUG: {message}");
                        return true;
                    }
                    return false;
                }
                public void Print(string message) {
                    Print(DebugUser, message, null);
                }
                public void Print(string message, object obj) {
                    Print(DebugUser, message, obj);
                }
                public void Print(IPlayer user, string message, object obj) {
                    if (!PrintInternal(user, obj == null ? message : $"{message}: {obj}")) {
                        Add(message, obj);
                    }
                }
                public void PrintLast(string id = null) {
                    if (_elements.Count > 0 && IsInstanceValid && Instance.DebugMode) {
                        PrintInternal(DebugUser, GetLast(id));
                    }
                }
                public string GetLast(string id = null) {
                    if (_elements.Count == 0) {
                        return m("CannotFindPosition", id);
                    }
                    var element = _elements.ElementAt(_elements.Count - 1);
                    _elements.Remove(element.Key);
                    return $"{element.Value.amount}x - {element.Key}{element.Value.ToString()}";
                }
            }
            public QueueController() {
                spawnChecks = Mathf.Clamp(config.Settings.Management.SpawnChecks, 1, 500);
            }
            public void StartCoroutine() {
                StopCoroutine();
                _coroutine = ServerMgr.Instance.StartCoroutine(FindEventPosition());
            }
            public void StopCoroutine() {
                if (_coroutine != null) {
                    ServerMgr.Instance.StopCoroutine(_coroutine);
                    _coroutine = null;
                }
                queue.ToList().ForEach(sp => {
                    sp.IsUnloading = true;
                    sp.payments?.Refund();
                }
                );
                queue.Clear();
            }
            public void Add(RandomBase sp) {
                if (!queue.Contains(sp)) {
                    queue.Enqueue(sp);
                }
            }
            private void Spawn(RandomBase rb, Vector3 position) {
                if (!rb.IsUnloading && IsInstanceValid) {
                    rb.Position = position;
                    if (Instance.PasteBuilding(rb)) {
                        RaidableBase.IsSpawnerBusy = true;
                        CompletePurchase(rb);
                        Teleport(rb);
                    }
                }
            }
            private void CompletePurchase(RandomBase rb) {
                if (rb.type == RaidableType.Purchased) {
                    if (rb.owner != null) {
                        var grid = FormatGridReference(rb.Position);
                        Message(rb.owner, "BuyBaseSpawnedAt", rb.Position, grid);
                        if (config.EventMessages.AnnounceBuy) {
                            foreach (var target in BasePlayer.activePlayerList) {
                                QueueNotification(target, "BuyBaseAnnouncement", rb.owner.displayName, rb.Position, grid);
                            }
                        }
                        Puts(mx("BuyBaseAnnouncementConsole", null, rb.owner.displayName, rb.Profile.Options.Mode, rb.BaseName, rb.Position, grid));
                    }
                    config.Settings.Buyable.Cooldowns.Set(rb.userid, rb.options.Mode);
                }
            }
            private void Teleport(RandomBase rb) {
                if (rb.user != null && rb.user.IsAdmin && rb.user.IsConnected) {
                    rb.user.Teleport(rb.Position.x, rb.Position.y, rb.Position.z);
                }
            }
            private bool CanBypassPause(RandomBase rb) {
                if (rb.type == RaidableType.Manual) {
                    return rb.user != null;
                }
                if (rb.type == RaidableType.Purchased) {
                    return rb.userid.HasPermission("raidablebases.canbypass");
                }
                return false;
            }
            private IEnumerator FindEventPosition() {
                CacheType cacheType;
                int checks = 0;
                RandomBase spq;
                string topology = "";
                while (true) {
                    if (++checks >= spawnChecks) {
                        yield return CoroutineEx.waitForSeconds(0.01f);
                        checks = 0;
                        continue;
                    }
                    if (!queue.TryPeek(out spq)) {
                        yield return CoroutineEx.waitForSeconds(pauseDelay);
                        continue;
                    }
                    if (!spq.IsUnloading && spq.Position != Vector3.zero) {
                        Spawn(spq, spq.Position);
                        yield return CoroutineEx.waitForSeconds(pauseDelay);
                        queue.Dequeue();
                        continue;
                    }
                    spq.TrySortByDistance();
                    spq.spawns.Check();
                    while (spq.hasSpawns) {
                        if (!IsInstanceValid || spq.IsUnloading) {
                            _coroutine = null;
                            yield break;
                        }
                        if (++checks >= spawnChecks) {
                            if (spq.type != RaidableType.Purchased && queue.Exists(sp => sp.type == RaidableType.Purchased)) {
                                break;
                            }
                            checks = 0;
                            yield return CoroutineEx.waitForSeconds(0.01f);
                        }
                        if (RaidableBase.IsSpawnerBusy || Paused && !CanBypassPause(spq)) {
                            yield return CoroutineEx.waitForSeconds(pauseDelay);
                            continue;
                        }
                        spq.attempts++;
                        var rsl = spq.spawns.GetRandom(spq.options.Water);
                        var vector = rsl.Location;
                        if (!TopologyChecks(spq, vector, topology)) {
                            continue;
                        }
                        vector.y = GetAdjustedHeight(spq, vector);
                        if (IsTooClose(spq, vector)) {
                            continue;
                        }
                        if (CanSpawnCustom(spq, vector)) {
                            yield return CoroutineEx.waitForSeconds(pauseDelay);
                            break;
                        }
                        if (CanSpawnCustomMaintained(spq, vector)) {
                            yield return CoroutineEx.waitForSeconds(pauseDelay);
                            break;
                        }
                        if (CanSpawnCustomSchedule(spq, vector)) {
                            yield return CoroutineEx.waitForSeconds(pauseDelay);
                            break;
                        }
                        if (CanSpawnCustomBuyable(spq, vector)) {
                            yield return CoroutineEx.waitForSeconds(pauseDelay);
                            break;
                        }
                        if (IsSubmerged(spq, rsl, vector)) {
                            continue;
                        }
                        if (!IsAreaSafe(spq, rsl, vector, out cacheType)) {
                            continue;
                        }
                        if (!spq.pasteData.valid) {
                            yield return SetupCopyPasteRadius(spq);
                        }
                        if (IsObstructed(spq, vector)) {
                            continue;
                        }
                        Messages.Add("Spawn location found", vector);
                        Spawn(spq, vector);
                        yield return CoroutineEx.waitForSeconds(pauseDelay);
                        break;
                    }
                    queue.Dequeue();
                    CheckSpawner(spq);
                }
                _coroutine = null;
            }
            private void CheckSpawner(RandomBase spq) {
                if (!RaidableBase.IsSpawnerBusy) {
                    if (spq.type == RaidableType.Manual) {
                        if (spq.user == null) {
                            Puts(mx("CannotFindPosition"));
                        }
                        else spq.user.Reply(m("CannotFindPosition", spq.user.Id));
                    }
                    else if (spq.isBuyableEvent) {
                        spq.payments?.Refund();
                        QueueNotification(spq.owner, "CannotFindPosition");
                    }
                    spq.spawns.TryAddRange();
                    Messages.PrintAll();
                }
            }
            private bool IsObstructed(RandomBase spq, Vector3 vector) {
                if (!spq.spawns.IsCustomSpawn && SpawnsController.IsObstructed(vector, spq.pasteData.radius, Mathf.Clamp(spq.options.LandLevel, -3f, 3f), spq.options.Setup.ForcedHeight, spq.options.Water.SpawnOnSeabed)) {
                    Messages.Add("Area is obstructed", vector);
                    spq.spawns.RemoveNear(vector, spq.protectionRadius / 2f, spq.options.Water.SpawnOnSeabed ? CacheType.Seabed : CacheType.Temporary, spq.type);
                    return true;
                }
                return false;
            }
            private IEnumerator SetupCopyPasteRadius(RandomBase spq) {
                yield return Instance.SetupCopyPasteObstructionRadius(spq.BaseName, spq.options.ProtectionRadii.Obstruction == -1 ? 0f : GetObstructionRadii(spq.options.ProtectionRadii, RaidableType.None));
            }
            private bool IsAreaSafe(RandomBase spq, RaidableSpawnLocation rsl, Vector3 vector, out CacheType cacheType) {
                if (!SpawnsController.IsAreaSafe(vector, spq.safeRadius, spq.buildRadius, layers, out cacheType, spq.type, spq.options.CustomSpawns)) {
                    if (spq.options.Water.SpawnOnSeabed) {
                        cacheType = CacheType.Seabed;
                    }
                    if (cacheType == CacheType.Delete) {
                        spq.spawns.Remove(rsl, cacheType);
                    }
                    else if (cacheType == CacheType.Privilege) {
                        spq.spawns.RemoveNear(vector, spq.buildRadius, cacheType, spq.type);
                    }
                    else spq.spawns.RemoveNear(vector, spq.safeRadius / 2f, cacheType, spq.type);
                    return false;
                }
                return true;
            }
            private bool IsSubmerged(RandomBase spq, RaidableSpawnLocation rsl, Vector3 vector) {
                if (!spq.spawns.IsCustomSpawn && spq.options.Setup.ForcedHeight == -1f && spq.options.Water.Seabed <= 0f && SpawnsController.IsSubmerged(spq.options.Water, rsl)) {
                    Messages.Add("Area is submerged", vector);
                    return true;
                }
                return false;
            }
            private bool CanSpawnCustomBuyable(RandomBase spq, Vector3 vector) {
                if (spq.type == RaidableType.Purchased && spq.spawns.IsCustomSpawn && (config.Settings.Buyable.Ignore || config.Settings.Buyable.SafeRadius > 0f)) {
                    if (config.Settings.Buyable.SafeRadius <= 0f) {
                        Messages.Add("Ignoring safe checks and spawning Buyable base", vector);
                        Spawn(spq, vector);
                        return true;
                    }
                    else spq.safeRadius = config.Settings.Buyable.SafeRadius;
                }
                return false;
            }
            private bool CanSpawnCustomSchedule(RandomBase spq, Vector3 vector) {
                if (spq.type == RaidableType.Scheduled && spq.spawns.IsCustomSpawn && (config.Settings.Schedule.Ignore || config.Settings.Schedule.SafeRadius > 0f)) {
                    if (config.Settings.Schedule.SafeRadius <= 0f) {
                        Messages.Add("Ignoring safe checks and spawning Scheduled base", vector);
                        Spawn(spq, vector);
                        return true;
                    }
                    else spq.safeRadius = config.Settings.Schedule.SafeRadius;
                }
                return false;
            }
            private bool CanSpawnCustomMaintained(RandomBase spq, Vector3 vector) {
                if (spq.type == RaidableType.Maintained && spq.spawns.IsCustomSpawn && (config.Settings.Maintained.Ignore || config.Settings.Maintained.SafeRadius > 0f)) {
                    if (config.Settings.Maintained.SafeRadius <= 0f) {
                        Messages.Add("Ignoring safe checks and spawning Maintained base", vector);
                        Spawn(spq, vector);
                        return true;
                    }
                    else spq.safeRadius = config.Settings.Maintained.SafeRadius;
                }
                return false;
            }
            private bool CanSpawnCustom(RandomBase spq, Vector3 vector) {
                if 
// ... [Code preview truncated due to length. Full source in attached file] ...

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

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

Сверху