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

FREE BuildingSites : 1.0.7 1.0.7

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Plugins.BuildingSitesExtensionMethods;
using Newtonsoft.Json;
using CompanionServer.Handlers;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("BuildingSites", "Forum: https://topplugin.ru Ds: alone_sempai Vk: https://vk.com/rustnastroika", "1.0.7")]
    class BuildingSites : RustPlugin {
#region Variables
        static BuildingSites ins;
        const bool en = false;
        HashSet<string> subscribeMethods = new HashSet<string> {
            "CanBuild", "OnEntitySpawned", "OnExplosiveThrown", "OnExplosiveDropped", "OnActiveItemChanged", "CanLootEntity", "OnEntityTakeDamage", "CanEntityTakeDamage"
        }
        ;
#endregion Variables
#region Hooks
        void Init() {
            Unsubscribes();
        }
        void OnServerInitialized() {
            ins = this;
            UpdateConfig();
            LoadDefaultMessages();
            if (!TryLoadData()) {
                NotifyManagerLite.PrintError(null, "DataNotFound_Exeption");
                NextTick(() => Interface.Oxide.UnloadPlugin(Name));
                return;
            }
            BuildingSite.Initialize();
            PlayerSiteSpawner.StartUpdate();
            PermissionManager.RegisterPermissions();
            Subscribes();
        }
        void Unload() {
            BuildingSite.UnloadSites();
            SiteSpawner.StopAutoSpawn();
            PlayerSiteSpawner.StopUpdate();
            Ch47Killer.Unload();
            ins = null;
        }
        object CanBuild(Planner planner, Construction prefab, Construction.Target constructionTarget) {
            if (!_config.skyTypeConfig.isTurretsDisable && !_config.skyTypeConfig.isSamsiteDisable) return null;
            BasePlayer player = planner.GetOwnerPlayer();
            Item item = planner.GetItem();
            if (item == null || player == null) return null;
            if ((_config.skyTypeConfig.isTurretsDisable && item.info.shortname == "autoturret") || (_config.skyTypeConfig.isSamsiteDisable && item.info.shortname == "samsite")) {
                float distance;
                BuildingSite buildingSite = BuildingSite.GetClosestSite<SkySiteConfig>(constructionTarget.position, out distance);
                if (buildingSite == null) return null;
                if (distance < buildingSite.siteConfig.outsideRadius * 1.5f) {
                    NotifyManagerLite.SendMessageToPlayer(player, "BlockedOnSite");
                    return true;
                }
            }
            return null;
        }
        void OnEntitySpawned(BuildingPrivlidge buildingPrivlidge) {
            if (buildingPrivlidge == null) return;
            NextTick(() => {
                BuildingSite buildingSite = BuildingSite.GetSiteByBuildingPrivilege(buildingPrivlidge);
                if (buildingSite != null) buildingSite.DeleteMapMarker();
            }
            );
        }
        void OnEntitySpawned(CH47HelicopterAIController ch47) {
            if (ch47 == null) return;
            Ch47Killer.AttachClass(ch47);
        }
        void OnExplosiveThrown(BasePlayer player, RoadFlare roadFlare, ThrownWeapon thrownWeapon) {
            OnPlayerDropFlare(player, roadFlare, thrownWeapon);
        }
        void OnExplosiveDropped(BasePlayer player, RoadFlare roadFlare, ThrownWeapon thrownWeapon) {
            OnPlayerDropFlare(player, roadFlare, thrownWeapon);
        }
        void OnPlayerDropFlare(BasePlayer player, RoadFlare roadFlare, ThrownWeapon thrownWeapon) {
            if (!player.IsRealPlayer() || roadFlare == null || thrownWeapon == null) return;
            Item item = thrownWeapon.GetItem();
            if (item == null) return;
            BaseSiteConfig baseSiteConfig = BuildingSite.GetSiteConfigBySkinId(item.skin);
            if (baseSiteConfig == null) return;
            SiteSpawnFlare.Attach(roadFlare, player, baseSiteConfig);
        }
        void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
            if (!player.IsRealPlayer() || newItem == null) return;
            if (newItem != null && newItem.info.shortname == "flare") {
                BaseSiteConfig baseSiteConfig = BuildingSite.GetSiteConfigBySkinId(newItem.skin);
                if (baseSiteConfig == null) return;
                BuildingSiteData siteData;
                ins.siteCustomizationDatas.TryGetValue(baseSiteConfig.dataFileName, out siteData);
                if (siteData == null) return;
                PlayerSiteSpawner.AddPlayer(player, baseSiteConfig);
                GroundSiteConfig groundSiteConfig = baseSiteConfig as GroundSiteConfig;
                if (groundSiteConfig != null) {
                    NotifyManagerLite.SendMessageToPlayer(player, "GroundFlare_Description", _config.prefix);
                    return;
                }
                WaterSiteConfig waterSiteConfig = baseSiteConfig as WaterSiteConfig;
                if (waterSiteConfig != null) {
                    NotifyManagerLite.SendMessageToPlayer(player, "WaterFlare_Description", _config.prefix);
                    return;
                }
                SkySiteConfig skySiteConfig = baseSiteConfig as SkySiteConfig;
                if (skySiteConfig != null) {
                    NotifyManagerLite.SendMessageToPlayer(player, "SkyFlare_Description", _config.prefix);
                    return;
                }
            }
        }
        object CanLootEntity(BasePlayer player, StorageContainer storageContainer) {
            if (player == null || storageContainer == null) return null;
            if (!ins._config.mainConfig.onlyAutedLootPumpjack) return null;
            if (storageContainer.ShortPrefabName == "fuelstorage" || storageContainer.ShortPrefabName == "crudeoutput") {
                MiningQuarry miningQuarry = storageContainer.GetParentEntity() as MiningQuarry;
                if (miningQuarry == null) return null;
                DoorCloser doorCloser = miningQuarry.GetParentEntity() as DoorCloser;
                if (doorCloser == null) return null;
                BuildingSite buildingSite = BuildingSite.GetSiteByEntity(doorCloser);
                if (buildingSite == null) return null;
                BuildingPrivlidge buildingPrivlidge = miningQuarry.GetBuildingPrivilege();
                if (buildingPrivlidge == null) buildingPrivlidge = doorCloser.GetBuildingPrivilege();
                if (buildingPrivlidge != null && !buildingPrivlidge.IsAuthed(player)) {
                    NotifyManagerLite.SendMessageToPlayer(player, "Unauthorized");
                    return true;
                }
            }
            return null;
        }
        object OnEntityTakeDamage(BuildingBlock buildingBlock, HitInfo info) {
            if (buildingBlock == null || info == null) return null;
            if (!buildingBlock.HasParent()) return null;
            BuildingSite buildingSite = BuildingSite.GetSiteByEntity(buildingBlock);
            if (buildingSite == null) return null;
            return true;
        }
        object CanEntityTakeDamage(BuildingBlock buildingBlock, HitInfo info) {
            if (buildingBlock == null || info == null) return null;
            if (!buildingBlock.HasParent()) return null;
            BuildingSite buildingSite = BuildingSite.GetSiteByEntity(buildingBlock);
            if (buildingSite == null) return null;
            return false;
        }
#endregion Hooks
#region Methods
        void UpdateConfig() {
            if (_config.version != Version) {
                PluginConfig defaultConfig = PluginConfig.DefaultConfig();
                if (_config.version.Patch <= 0) {
                    if (_config.markerConfig.displayedName == "Свободное место под застройку") _config.markerConfig.displayedName = defaultConfig.markerConfig.displayedName;
                    foreach (BaseSiteConfig baseSiteConfig in _config.groundTypeConfig.sites) baseSiteConfig.permission = "";
                    foreach (BaseSiteConfig baseSiteConfig in _config.waterTypeConfig.sites) baseSiteConfig.permission = "";
                    foreach (BaseSiteConfig baseSiteConfig in _config.skyTypeConfig.sites) baseSiteConfig.permission = "";
                }
                if (_config.version.Patch <= 1) {
                    _config.mainConfig = defaultConfig.mainConfig;
                }
                _config.version = Version;
                SaveConfig();
            }
        }
        void Unsubscribes() {
            foreach (string hook in subscribeMethods) Unsubscribe(hook);
        }
        void Subscribes() {
            foreach (string hook in subscribeMethods) Subscribe(hook);
        }
        static void Debug(params object[] arg) {
            string result = "";
            foreach (object obj in arg) if (obj != null) result += obj.ToString() + " ";
            ins.Puts(result);
        }
#endregion Methods
#region Commands
        [ChatCommand("respawnsites")]
        void RespawnSitesChatCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            SiteSpawner.StartAutoSpawn();
            NotifyManagerLite.SendMessageToPlayer(player, "Spawn_Start");
        }
        [ConsoleCommand("spawnsite")]
        void RespawnSitesConsoleCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() != null) return;
            SiteSpawner.StartAutoSpawn();
            NotifyManagerLite.PrintLogMessage("Spawn_Start");
        }
        [ChatCommand("spawnsite")]
        void SpawnSiteChatCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || arg.Length < 1) return;
            string presetName = arg[0];
            BaseSiteConfig siteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
            if (siteConfig == null) {
                NotifyManagerLite.PrintError(player, "ConfigNotFound_Exeption", presetName);
                return;
            }
            SiteSpawner.SpawnSiteInRandomLocation(presetName);
            NotifyManagerLite.SendMessageToPlayer(player, "Spawn_Start");
        }
        [ConsoleCommand("spawnsite")]
        void SpawnSiteConsoleCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() != null || arg.Args.Length < 1) return;
            string presetName = arg.Args[0];
            BaseSiteConfig siteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
            if (siteConfig == null) {
                NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
                return;
            }
            SiteSpawner.SpawnSiteInRandomLocation(presetName);
            NotifyManagerLite.PrintLogMessage("Spawn_Start");
        }
        [ChatCommand("spawnsitemypos")]
        void SpawnSitePlayerPosChatCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            string presetName = arg[0];
            BaseSiteConfig siteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
            if (siteConfig == null) {
                NotifyManagerLite.PrintError(player, "ConfigNotFound_Exeption", presetName);
                return;
            }
            BuildingSite.SpawnSite(presetName, player.transform.position, Quaternion.identity);
        }
        [ChatCommand("givesite")]
        void GiveSiteChatCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || arg.Length < 1) return;
            string presetName = arg[0];
            BaseSiteConfig siteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
            if (siteConfig == null) {
                NotifyManagerLite.PrintError(player, "ConfigNotFound_Exeption", presetName);
                return;
            }
            LootManager.GiveItemToPLayer(player, siteConfig.itemConfig, 1);
        }
        [ConsoleCommand("givesite")]
        void GiveSiteConsoleCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() != null || arg.Args.Length < 2) return;
            string presetName = arg.Args[0];
            BaseSiteConfig siteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
            if (siteConfig == null) {
                NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
                return;
            }
            ulong targetUserId = Convert.ToUInt64(arg.Args[1]);
            BasePlayer targetPlayer = BasePlayer.FindByID(targetUserId);
            if (targetPlayer == null) {
                NotifyManagerLite.PrintError(null, "PlayerNotFound_Exeption", arg.Args[1]);
                return;
            }
            LootManager.GiveItemToPLayer(targetPlayer, siteConfig.itemConfig, 1);
            NotifyManagerLite.SendMessageToPlayer(targetPlayer, "GotSite");
        }
        [ConsoleCommand("killallsites")]
        void KillAllSitesCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() != null) return;
            BuildingSite.KillAllSites();
        }
        [ChatCommand("killallsites")]
        void KillAllSitesChatCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            BuildingSite.KillAllSites();
        }
        [ChatCommand("killsite")]
        void KillSiteCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            BaseEntity target = PositionDefiner.RaycastAll<BaseEntity>(player.eyes.HeadRay());
            if (target == null) return;
            BuildingSite buildingSite = BuildingSite.GetSiteByEntity(target);
            if (buildingSite == null) return;
            buildingSite.KillSite();
        }
        [ChatCommand("savemapsite")]
        void SaveMapCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            string locationName = arg[0];
            MapSaver.SaveMap(locationName);
        }
#endregion Commands
#region Classes
        static class PlayerSiteSpawner {
            static HashSet<PlayerFlareInfo> playersWithFlare = new HashSet<PlayerFlareInfo>();
            static Coroutine updateCorountine;
            internal static void AddPlayer(BasePlayer player, BaseSiteConfig baseSiteConfig) {
                if (playersWithFlare.Any(x => x.player != null && x.player.userID == player.userID)) return;
                PlayerFlareInfo playerFlareData = new PlayerFlareInfo(player, baseSiteConfig);
                playersWithFlare.Add(playerFlareData);
            }
            internal static void StartUpdate() {
                updateCorountine = ServerMgr.Instance.StartCoroutine(SpawnLocationCoroutine());
            }
            internal static void StopUpdate() {
                if (updateCorountine != null) ServerMgr.Instance.StopCoroutine(updateCorountine);
            }
            static IEnumerator SpawnLocationCoroutine() {
                while (true) {
                    playersWithFlare.RemoveWhere(x => !IsFlareDataActive(x));
                    foreach (PlayerFlareInfo playerFlareData in playersWithFlare) {
                        DisplayPlayerData(playerFlareData);
                    }
                    yield return CoroutineEx.waitForSeconds(1f);
                }
            }
            static void DisplayPlayerData(PlayerFlareInfo playerFlareData) {
                if (!string.IsNullOrEmpty(playerFlareData.siteConfig.permission) && !PermissionManager.IsUserHavePermission(playerFlareData.player.UserIDString, playerFlareData.siteConfig.permission)) {
                    NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "NoPermission");
                    return;
                }
                HashSet<BaseEntity> entities = new HashSet<BaseEntity>();
                Vector3 spawnPosition = playerFlareData.player.transform.position;
                bool isPlacesuitable = SiteSpawner.IsPositionAvilable(ref spawnPosition, playerFlareData.siteConfig, out entities, true);
                if (isPlacesuitable) NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "Position_Suitable");
                else NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "Position_NotSuitable");
            }
            static bool IsFlareDataActive(PlayerFlareInfo playerFlareData) {
                if (playerFlareData.player == null || playerFlareData.player.IsSleeping()) return false;
                Item activeItem = playerFlareData.player.GetActiveItem();
                if (activeItem == null || activeItem.info.shortname != "flare") return false;
                return true;
            }
        }
        class SiteSpawnFlare : FacepunchBehaviour {
            RoadFlare roadFlare;
            PlayerFlareInfo playerFlareData;
            internal static SiteSpawnFlare Attach(RoadFlare roadFlare, BasePlayer player, BaseSiteConfig siteConfig) {
                SiteSpawnFlare siteSpawnFlare = roadFlare.gameObject.AddComponent<SiteSpawnFlare>();
                siteSpawnFlare.Init(roadFlare, player, siteConfig);
                return siteSpawnFlare;
            }
            void Init(RoadFlare roadFlare, BasePlayer player, BaseSiteConfig siteConfig) {
                playerFlareData = new PlayerFlareInfo(player, siteConfig);
                this.roadFlare = roadFlare;
                roadFlare.enableSaving = false;
                roadFlare.waterCausesExplosion = false;
                if (!string.IsNullOrEmpty(siteConfig.permission) && !PermissionManager.IsUserHavePermission(player.UserIDString, siteConfig.permission)) {
                    LootManager.GiveItemToPLayer(player, playerFlareData.siteConfig.itemConfig, 1);
                    NotifyManagerLite.SendMessageToPlayer(player, "NoPermission");
                    roadFlare.Kill();
                    return;
                }
                roadFlare.Invoke(CallSite, siteConfig is WaterSiteConfig ? 30f : 15f);
                SphereEntity sphereEntity = BuildManager.SpawnChildEntity(roadFlare, "assets/bundled/prefabs/modding/events/twitch/br_sphere_red.prefab", Vector3.zero, Vector3.zero, isDecor : false) as SphereEntity;
                sphereEntity.LerpRadiusTo(100, float.MaxValue);
                if (siteConfig is WaterSiteConfig) roadFlare.InvokeRepeating(WaterCheck, 1f, 1f);
            }
            void OnCollisionEnter(Collision collision) {
                Rigidbody rigidbody = roadFlare.GetComponent<Rigidbody>();
                rigidbody.isKinematic = true;
            }
            void WaterCheck() {
                if (roadFlare.transform.position.y <= 0) {
                    Rigidbody rigidbody = roadFlare.GetComponent<Rigidbody>();
                    rigidbody.isKinematic = true;
                    roadFlare.transform.position = new Vector3(roadFlare.transform.position.x, 0, roadFlare.transform.position.z);
                    roadFlare.CancelInvoke(WaterCheck);
                }
            }
            void CallSite() {
                if (ins._config.mainConfig.maxLocationNumberPerPlayer >= 0) {
                    HashSet<BuildingSite> playerSites = BuildingSite.GetPlayersSites(playerFlareData.player.userID);
                    int playerSitesCount = playerSites.Count;
                    if (playerSitesCount >= ins._config.mainConfig.maxLocationNumberPerPlayer) {
                        LootManager.GiveItemToPLayer(playerFlareData.player, playerFlareData.siteConfig.itemConfig, 1);
                        NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "MaxSitesForPlayer");
                        roadFlare.Kill();
                        return;
                    }
                }
                BuildingSite buildingSite = SiteSpawner.TrySpawnSite(this.transform.position, playerFlareData.siteConfig);
                if (buildingSite == null) {
                    LootManager.GiveItemToPLayer(playerFlareData.player, playerFlareData.siteConfig.itemConfig, 1);
                    NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "Spawn_Failed");
                }
                else {
                    buildingSite.SetSiteOwner(playerFlareData.player.userID);
                }
                roadFlare.Kill();
            }
        }
        class PlayerFlareInfo {
            internal BasePlayer player;
            internal BaseSiteConfig siteConfig;
            internal PlayerFlareInfo(BasePlayer player, BaseSiteConfig siteConfig) {
                this.player = player;
                this.siteConfig = siteConfig;
            }
        }
        static class SiteSpawner {
            static Coroutine spawnCorountine;
            internal static void StartAutoSpawn() {
                if (!ins._config.groundTypeConfig.isAutoSpawn && !ins._config.waterTypeConfig.isAutoSpawn && !ins._config.skyTypeConfig.isAutoSpawn) return;
                spawnCorountine = ServerMgr.Instance.StartCoroutine(AutoSpawnCoroutine());
            }
            static IEnumerator AutoSpawnCoroutine() {
                NotifyManagerLite.PrintWarningMessage("SpawnStart_Log");
                int groundSitesCount = UnityEngine.Random.Range(ins._config.groundTypeConfig.minAmount, ins._config.groundTypeConfig.maxAmount);
                if (ins._config.groundTypeConfig.isAutoSpawn && groundSitesCount > 0) {
                    for (int i = 0; i < groundSitesCount; i++) {
                        BaseSiteConfig siteConfig = GetRandomSiteConfig(ins._config.groundTypeConfig.sites);
                        yield return SpawnLocationCoroutine(siteConfig);
                    }
                }
                int waterSitesCount = UnityEngine.Random.Range(ins._config.waterTypeConfig.minAmount, ins._config.waterTypeConfig.maxAmount);
                if (ins._config.waterTypeConfig.isAutoSpawn && waterSitesCount > 0) {
                    for (int i = 0; i < waterSitesCount; i++) {
                        BaseSiteConfig siteConfig = GetRandomSiteConfig(ins._config.waterTypeConfig.sites);
                        yield return SpawnLocationCoroutine(siteConfig);
                    }
                }
                int skySitesCount = UnityEngine.Random.Range(ins._config.skyTypeConfig.minAmount, ins._config.skyTypeConfig.maxAmount);
                if (ins._config.skyTypeConfig.isAutoSpawn && skySitesCount > 0) {
                    for (int i = 0; i < skySitesCount; i++) {
                        BaseSiteConfig siteConfig = GetRandomSiteConfig(ins._config.skyTypeConfig.sites);
                        yield return SpawnLocationCoroutine(siteConfig);
                    }
                }
                NotifyManagerLite.PrintWarningMessage("SpawnStop_Log");
                yield return CoroutineEx.waitForSeconds(1);
            }
            static BaseSiteConfig GetRandomSiteConfig(IEnumerable<BaseSiteConfig> siteConfigs) {
                float sumChance = 0;
                foreach (BaseSiteConfig baseSiteConfig in siteConfigs) sumChance += baseSiteConfig.probability;
                float random = UnityEngine.Random.Range(0, sumChance);
                foreach (BaseSiteConfig baseSiteConfig in siteConfigs) {
                    random -= baseSiteConfig.probability;
                    if (random <= 0) return baseSiteConfig;
                }
                return null;
            }
            internal static void StopAutoSpawn() {
                if (spawnCorountine != null) ServerMgr.Instance.StopCoroutine(spawnCorountine);
            }
            internal static void SpawnSiteInRandomLocation(string presetName) {
                BaseSiteConfig baseSiteConfig = BuildingSite.GetSiteConfigByPresetName(presetName);
                if (baseSiteConfig == null) {
                    NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
                    return;
                }
                BuildingSiteData siteData;
                ins.siteCustomizationDatas.TryGetValue(baseSiteConfig.dataFileName, out siteData);
                if (siteData == null) {
                    NotifyManagerLite.PrintError(null, "DataFileNotFound_Exeption", baseSiteConfig.dataFileName);
                    return;
                }
                ServerMgr.Instance.StartCoroutine(SpawnLocationCoroutine(baseSiteConfig));
            }
            static IEnumerator SpawnLocationCoroutine(BaseSiteConfig siteConfig) {
                int counter = 5000;
                bool isSpawned = false;
                while (counter-- > 0) {
                    Vector3 position = PositionDefiner.GetRandomMapPoint();
                    if (TrySpawnSite(position, siteConfig) != null) isSpawned = true;
                    if (isSpawned) break;
                    else if (counter % 3 == 0) yield return CoroutineEx.waitForEndOfFrame;
                }
                if (!isSpawned) NotifyManagerLite.PrintError(null, $"FailedToSpawn {siteConfig.presetName}");
                yield return CoroutineEx.waitForSeconds(3f);
            }
            internal static BuildingSite TrySpawnSite(Vector3 position, BaseSiteConfig siteConfig) {
                HashSet<BaseEntity> entitiesForDestroy;
                if (IsPositionAvilable(ref position, siteConfig, out entitiesForDestroy)) {
                    return SpawnSite(siteConfig.presetName, position, entitiesForDestroy);
                }
                return null;
            }
            internal static bool IsPositionAvilable(ref Vector3 position, BaseSiteConfig siteConfig, out HashSet<BaseEntity> entitiesForDestroy, bool ignorePlayers = false) {
                entitiesForDestroy = new HashSet<BaseEntity>();
                GroundSiteConfig groundSiteConfig = siteConfig as GroundSiteConfig;
                if (groundSiteConfig != null) {
                    if (IsGroundPositionAvailable(position, groundSiteConfig, out entitiesForDestroy, ignorePlayers)) return true;
                    return false;
                }
                WaterSiteConfig waterSiteConfig = siteConfig as WaterSiteConfig;
                if (waterSiteConfig != null) {
                    position.y = 0;
                    if (IsWaterPositionAvailable(position, waterSiteConfig, out entitiesForDestroy, ignorePlayers)) return true;
                    return false;
                }
                SkySiteConfig skySiteConfig = siteConfig as SkySiteConfig;
                if (skySiteConfig != null) {
                    position.y = UnityEngine.Random.Range(ins._config.skyTypeConfig.minSpawnHeight, ins._config.skyTypeConfig.maxSpawnHeight);
                    if (IsSkyPositionAvailable(position, skySiteConfig, ignorePlayers)) return true;
                    return false;
                }
                return false;
            }
            static BuildingSite SpawnSite(string sitePresetName, Vector3 position, HashSet<BaseEntity> entitiesForDestroy) {
                foreach (BaseEntity entity in entitiesForDestroy) if (entity.IsExists()) entity.Kill();
                Quaternion randomRotation = Quaternion.Euler(0, UnityEngine.Random.Range(0, 360f), 0);
                return BuildingSite.SpawnSite(sitePresetName, position, randomRotation);
            }
            static bool IsGroundPositionAvailable(Vector3 position, GroundSiteConfig groundSiteConfig, out HashSet<BaseEntity> entitiesForDestroy, bool ignorePlayers) {
                entitiesForDestroy = new HashSet<BaseEntity>();
                float mapHeigth = TerrainMeta.HeightMap.GetHeight(position);
                if (mapHeigth < -ins._config.groundTypeConfig.maxDepht) return false;
                if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, groundSiteConfig)) return false;
                if (IsPositionBlockedByTopology(position, groundSiteConfig)) return false;
                if (IsPositionBlockByHeigthInRadius(position, groundSiteConfig.insideRadius, groundSiteConfig.maxUpDeltaHeigh, groundSiteConfig.maxDownDeltaHeigh)) return false;
                if (IsPositionBlockByHeigthInRadius(position, groundSiteConfig.insideRadius * 0.5f, groundSiteConfig.maxUpDeltaHeigh, groundSiteConfig.maxDownDeltaHeigh)) return false;
                if (IsAnyEntityBlockSpawn(position, groundSiteConfig, out entitiesForDestroy, ignorePlayers)) return false;
                return true;
            }
            static bool IsAnyEntityBlockSpawn(Vector3 position, BaseSiteConfig baseSiteConfig, out HashSet<BaseEntity> entitiesForDestroy, bool ignorePlayers) {
                entitiesForDestroy = new HashSet<BaseEntity>();
                foreach (Collider collider in UnityEngine.Physics.OverlapSphere(position, baseSiteConfig.outsideRadius)) {
                    if (collider.name.Contains("heatSource")) continue;
                    if (collider.name.Contains("Safe") || collider.name.Contains("Trigger (8)")) return true;
                    BaseEntity entity = collider.ToBaseEntity();
                    if (entity == null) {
                        string colliderLowerName = collider.name.ToLower();
                        if (colliderLowerName.Contains("prevent_building") || colliderLowerName.Contains("preventbuilding") || colliderLowerName.Contains("prevent building")) return true;
                        continue;
                    }
                    if (entity.GetBuildingPrivilege() != null) return true;
                    if (ignorePlayers && entity is BaseBoat && baseSiteConfig is WaterSiteConfig) continue;
                    if (entity is BuildingBlock or SimpleBuildingBlock or BaseVehicle) return true;
                    if (!ignorePlayers && entity is BasePlayer) return true;
                    if (entity is JunkPile or DiveSite or LootContainer or OreResourceEntity or BasePortal) entitiesForDestroy.Add(entity);
                    else if (ins._config.mainConfig.killTrees && entity is TreeEntity) entitiesForDestroy.Add(entity);
                }
                return false;
            }
            static bool IsPositionBlockedByTopology(Vector3 postition, BaseSiteConfig baseSiteConfig, int angleStep = 15) {
                if (TopologyChecker.IsPositionBlockedByTopologies(postition, baseSiteConfig)) return true;
                for (int angle = 0; angle < 360; angle += angleStep) {
                    float radian = 2f * Mathf.PI * angle / 360;
                    float x = postition.x + baseSiteConfig.outsideRadius * Mathf.Cos(radian);
                    float z = postition.z + baseSiteConfig.outsideRadius * Mathf.Sin(radian);
                    Vector3 positionInRadius = PositionDefiner.GetGroundPosition(new Vector3(x, postition.y, z));
                    if (TopologyChecker.IsPositionBlockedByTopologies(positionInRadius, baseSiteConfig)) return true;
                    if (baseSiteConfig is WaterSiteConfig && !TopologyChecker.IsOceanTopology(positionInRadius)) return true;
                }
                return false;
            }
            static bool IsPositionBlockByHeigthInRadius(Vector3 postition, float radius, float maxUpDelta, float maxDownDelta, int angleStep = 15) {
                for (int angle = 0; angle < 360; angle += angleStep) {
                    float radian = 2f * Mathf.PI * angle / 360;
                    float x = postition.x + radius * Mathf.Cos(radian);
                    float z = postition.z + radius * Mathf.Sin(radian);
                    Vector3 positionInRadius = PositionDefiner.GetGroundPosition(new Vector3(x, postition.y, z));
                    float delta = positionInRadius.y - postition.y;
                    if (delta > 0 && delta > maxUpDelta) return true;
                    if (delta < 0 && -delta > maxDownDelta) return true;
                }
                return false;
            }
            static bool IsWaterPositionAvailable(Vector3 position, WaterSiteConfig waterSiteConfig, out HashSet<BaseEntity> entitiesForDestroy, bool ignorePlayers) {
                entitiesForDestroy = new HashSet<BaseEntity>();
                float mapHeigth = TerrainMeta.HeightMap.GetHeight(position);
                if (-mapHeigth < ins._config.waterTypeConfig.minDepth) return false;
                if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, waterSiteConfig)) return false;
                if (GetShoreDistance(position) > ins._config.waterTypeConfig.maxShoreDistance) return false;
                if (!IsPositionInMapBounds(position, waterSiteConfig)) return false;
                if (IsPositionBlockedByTopology(position, waterSiteConfig)) return false;
                if (PositionDefiner.IsPositionOnCargoPath(position)) return false;
                if (IsAnyEntityBlockSpawn(position, waterSiteConfig, out entitiesForDestroy, ignorePlayers)) return false;
                return true;
            }
            static float GetShoreDistance(Vector3 position) {
                float xDistanceToShore = position.x - World.Size / 2;
                float zDistanceToShore = position.z - World.Size / 2;
                float distanceToShore = xDistanceToShore > zDistanceToShore ? xDistanceToShore : zDistanceToShore;
                //Distance to shore = 32339
                return distanceToShore;
            }
            static bool IsSkyPositionAvailable(Vector3 position, SkySiteConfig skySiteConfig, bool ignorePlayers) {
                HashSet<BaseEntity> entitiesForDestroy = new HashSet<BaseEntity>();
                Vector3 groundPosition = PositionDefiner.GetGroundPosition(position);
                float distanceToGround = position.y - groundPosition.y;
                if (distanceToGround < ins._config.skyTypeConfig.minSpawnHeight / 2.5f) return false;
                if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, skySiteConfig)) return false;
                if (!IsPositionInMapBounds(position, skySiteConfig)) return false;
                if (IsAnyEntityBlockSpawn(position, skySiteConfig, out entitiesForDestroy, ignorePlayers)) return false;
                return true;
            }
            static bool IsPositionInMapBounds(Vector3 position, BaseSiteConfig baseSiteConfig) {
                if (Mathf.Abs(position.x) + baseSiteConfig.outsideRadius > World.Size / 2) return false;
                if (Mathf.Abs(position.z) + baseSiteConfig.outsideRadius > World.Size / 2) return false;
                return true;
            }
        }
        static class TopologyChecker {
            const int oceanTopologies = (int)(TerrainTopology.Enum.Ocean | TerrainTopology.Enum.Oceanside);
            const int blockedTopologies = (int)(TerrainTopology.Enum.Building | TerrainTopology.Enum.Road | TerrainTopology.Enum.Roadside | TerrainTopology.Enum.Rail | TerrainTopology.Enum.Railside);
            const int monumentTopologies = (int)(TerrainTopology.Enum.Monument | TerrainTopology.Enum.Building);
            const int beachTopologies = (int)(TerrainTopology.Enum.Beach | TerrainTopology.Enum.Beachside);
            const int riverTopologies = (int)(TerrainTopology.Enum.River | TerrainTopology.Enum.Riverside | TerrainTopology.Enum.Lake | TerrainTopology.Enum.Lakeside);
            internal static bool IsPositionBlockedByTopologies(Vector3 postition, BaseSiteConfig baseSiteConfig) {
                if (TopologyChecker.IsBlockedTopology(postition)) return true;
                if (!ins._config.groundTypeConfig.isRiverSpawnEnabled && TopologyChecker.IsRiverOrLakeTopology(postition)) return true;
                if (baseSiteConfig is GroundSiteConfig && !ins._config.groundTypeConfig.isBeachSpawnEnabled && (TopologyChecker.IsBeachTopology(postition) || TopologyChecker.IsOceanTopology(postition))) return true;
                return false;
            }
            static bool IsBlockedTopology(Vector3 position) {
                int pointTopologies = TerrainMeta.TopologyMap.GetTopology(position);
                if ((pointTopologies & blockedTopologies) != 0) return true;
                if ((pointTopologies & monumentTopologies) != 0) return true;
                return false;
            }
            static bool IsBeachTopology(Vector3 position) {
                int pointTopologies = TerrainMeta.TopologyMap.GetTopology(position);
                if ((pointTopologies & beachTopologies) != 0) return true;
                return false;
            }
            static bool IsRiverOrLakeTopology(Vector3 position) {
                int pointTopologies = TerrainMeta.TopologyMap.GetTopology(position);
                if ((pointTopologies & riverTopologies) != 0) return true;
                return false;
            }
            internal static bool IsOceanTopology(Vector3 position) {
                int pointTopologies = TerrainMeta.TopologyMap.GetTopology(position);
                if ((pointTopologies & oceanTopologies) != 0) return true;
                return false;
            }
        }
        class BuildingSite : FacepunchBehaviour {
            static HashSet<BuildingSite> buildingSites = new HashSet<BuildingSite>();
            internal BaseSiteConfig siteConfig;
            BaseEntity mainEntity;
            BuildingSiteData siteData;
            MapMarker mapMarker;
            HashSet<GameObject> shoudDestroyAfterUnload = new HashSet<GameObject>();
            internal static void Initialize() {
                LoadSites();
                if (buildingSites.Count == 0) SiteSpawner.StartAutoSpawn();
            }
            static void LoadSites() {
                HashSet<DoorCloser> doorClosers = BaseNetworkable.serverEntities.OfType<DoorCloser>();
                foreach (DoorCloser doorCloser in doorClosers) {
                    if (doorCloser == null || doorCloser.net == null) continue;
                    BaseSiteConfig siteConfig = GetSiteConfigBySkinId(doorCloser.skinID);
                    if (siteConfig == null) continue;
                    BuildingSite buildingSite = TryAttachBuildingSiteClass(doorCloser, siteConfig.presetName, false);
                }
            }
            internal static BaseSiteConfig GetSiteConfigByPresetName(string presetName) {
                BaseSiteConfig result = null;
                result = ins._config.groundTypeConfig.sites.FirstOrDefault(x => x.presetName == presetName);
                if (result == null) result = ins._config.waterTypeConfig.sites.FirstOrDefault(x => x.presetName == presetName);
                if (result == null) result = ins._config.skyTypeConfig.sites.FirstOrDefault(x => x.presetName == presetName);
                return result;
            }
            internal static BaseSiteConfig GetSiteConfigBySkinId(ulong skinID) {
                BaseSiteConfig result = null;
                result = ins._config.groundTypeConfig.sites.FirstOrDefault(x => x.itemConfig.skin == skinID);
                if (result == null) result = ins._config.waterTypeConfig.sites.FirstOrDefault(x => x.itemConfig.skin == skinID);
                if (result == null) result = ins._config.skyTypeConfig.sites.FirstOrDefault(x => x.itemConfig.skin == skinID);
                return result;
            }
            internal static BuildingSite GetSiteByEntity(BaseEntity entity) {
                return buildingSites.FirstOrDefault(x => x != null && x.mainEntity.IsExists() && x.IsSiteEntity(entity));
            }
            internal static BuildingSite GetSiteByBuildingPrivilege(BuildingPrivlidge buildingPrivlidge) {
                foreach (BuildingSite buildingSite in buildingSites) {
                    if (buildingSite == null || buildingSite.mainEntity == null) return null;
                    BuildingPrivlidge sitePrivilege = buildingSite.mainEntity.GetBuildingPrivilege();
                    if (sitePrivilege != null && sitePrivilege.net != null && sitePrivilege.net.ID.Value == buildingPrivlidge.net.ID.Value) return buildingSite;
                    foreach (BaseEntity childEntity in buildingSite.mainEntity.children) {
                        if (!childEntity.ShortPrefabName.Contains("admin")) continue;
                        sitePrivilege = childEntity.GetBuildingPrivilege();
                        if (sitePrivilege != null && sitePrivilege.net != null && sitePrivilege.net.ID.Value == buildingPrivlidge.net.ID.Value) return buildingSite;
                    }
                }
                return null;
            }
            internal static BuildingSite GetClosestSite<ConfigType>(Vector3 position, out float minDistance) where ConfigType : BaseSiteConfig {
                minDistance = float.MaxValue;
                BuildingSite result = null;
                foreach (BuildingSite buildingSite in buildingSites) {
                    if (buildingSite == null || buildingSite.siteConfig is not ConfigType) continue;
                    Vector3 offset = buildingSite.siteData.offset.ToVector3();
                    float distance = Vector3.Distance(position, buildingSite.mainEntity.transform.position + offset);
                    if (distance < minDistance) {
                        minDistance = distance;
                        result = buildingSite;
                    }
                }
                return result;
            }
            internal static HashSet<BuildingSite> GetPlayersSites(ulong userID) {
                return buildingSites.Where(x => x != null && x.mainEntity.IsExists() && x.mainEntity.OwnerID == userID);
            }
            internal static bool IsSpawnPositionBlockByOtherSite(Vector3 position, BaseSiteConfig siteConfig) {
                position.y = 0;
                foreach (BuildingSite site in buildingSites) {
                    if (site == null || !site.mainEntity.IsExists()) continue;
                    Vector3 siteGroundPosition = new Vector3(site.mainEntity.transform.position.x, 0, site.mainEntity.transform.position.z);
                    float distance = Vector3.Distance(position, siteGroundPosition);
                    if (distance < (siteConfig.outsideRadius + site.siteConfig.outsideRadius) * 1.5f) return true;
                }
                return false;
            }
            internal static BuildingSite SpawnSite(string presetName, Vector3 position, Quaternion rotation) {
                BaseSiteConfig siteConfig = GetSiteConfigByPresetName(presetName);
                if (siteConfig == null) {
                    NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
                    return null;
                }
                BaseEntity mainEntity = BuildManager.SpawnRegularEntity("assets/prefabs/misc/doorcloser/doorcloser.prefab", position, rotation, siteConfig.itemConfig.skin, true);
                BuildingSite buildingSite = TryAttachBuildingSiteClass(mainEntity, presetName, true);
                if (buildingSite == null) mainEntity.Kill();
                return buildingSite;
            }
            static BuildingSite TryAttachBuildingSiteClass(BaseEntity mainEntity, string presetName, bool firstSpawn) {
                BaseSiteConfig siteConfig = GetSiteConfigByPresetName(presetName);
                if (siteConfig == null) {
                    NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
                    return null;
                }
                BuildingSiteData siteData;
                ins.siteCustomizationDatas.TryGetValue(siteConfig.dataFileName, out siteData);
                if (siteData == null) {
                    NotifyManagerLite.PrintError(null, "DataFileNotFound_Exeption", siteConfig.dataFileName);
                    return null;
                }
                BuildingSite buildingSite = mainEntity.gameObject.AddComponent<BuildingSite>();
                buildingSites.Add(buildingSite);
                buildingSite.BuildSite(mainEntity, siteConfig, siteData, firstSpawn);
                return buildingSite;
            }
            void BuildSite(BaseEntity mainEntity, BaseSiteConfig siteConfig, BuildingSiteData siteData, bool firstSpawn) {
                this.mainEntity = mainEntity;
                this.siteConfig = siteConfig;
                this.siteData = siteData;
                Vector3 offset = siteData.offset.ToVector3();
                foreach (EntityData entityData in siteData.decorEntities) {
                    Vector3 localPosition = entityData.position.ToVector3() + offset;
                    Vector3 localRotation = entityData.rotation.ToVector3();
                    if (!firstSpawn && mainEntity.children.Any(x => x != null && x.PrefabName == entityData.prefabName && x.transform.localPosition == localPosition)) continue;
                    BaseEntity entity = BuildManager.SpawnChildEntity(mainEntity, entityData.prefabName, localPosition, localRotation, isDecor : true, enableSaving : false);
                    if (entity.ShortPrefabName == "coaling_tower_fuel_storage.entity" || entity.ShortPrefabName == "mailbox.deployed") entity.SetFlag(BaseEntity.Flags.Busy, true);
                    if (entity.ShortPrefabName == "hotairballoon") {
                        entity.SetFlag(BaseEntity.Flags.On, true);
                        entity.SetFlag(BaseEntity.Flags.Reserved11, true);
                        entity.SetFlag(BaseEntity.Flags.Reserved12, true);
                        entity.SetFlag(BaseEntity.Flags.Reserved13, true);
                        entity.SendNetworkUpdate();
                    }
                }
                foreach (BuildingBlockData buildingBlockData in siteData.buildingBlocks) {
                    Vector3 localPosition = buildingBlockData.position.ToVector3() + offset;
                    Vector3 localRotation = buildingBlockData.rotation.ToVector3();
                    BuildingBlock thisBuildingBlock = mainEntity.children.FirstOrDefault(x => x != null && x.PrefabName == buildingBlockData.prefabName && x.transform.localPosition == localPosition && x.transform.localEulerAngles == localRotation) as BuildingBlock;
                    if (thisBuildingBlock != null) {
                        thisBuildingBlock.grounded = true;
                        continue;
                    }
                    BuildingBlock buildingBlock = BuildManager.SpawnChildBuildingBlock(buildingBlockData.prefabName, buildingBlockData.grade, buildingBlockData.color, buildingBlockData.skin, localPosition, localRotation, mainEntity);
                    buildingBlock.grounded = true;
                }
                foreach (EntityData regularEntityData in siteData.regularEntities) {
                    Vector3 localPosition = regularEntityData.position.ToVector3() + offset;
                    Vector3 localRotation = regularEntityData.rotation.ToVector3();
                    if (!firstSpawn && mainEntity.children.Any(x => x != null && x.PrefabName == regularEntityData.prefabName && Vector3.Distance(x.transform.localPosition, localPosition) < 0.1f)) continue;
                    BaseEntity baseEntity = BuildManager.SpawnChildEntity(mainEntity, regularEntityData.prefabName, localPosition, localRotation, isDecor : false, enableSaving : true);
                    if (baseEntity is Pe
// ... [Code preview truncated due to length. Full source in attached file] ...

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