C#:
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;
using System.IO;
namespace Oxide.Plugins {
[Info("BuildingSites", "Adem", "1.1.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"
}
;
Coroutine spawnCorountine;
HashSet<PlayerFlareInfo> playersWithFlare = new HashSet<PlayerFlareInfo>();
HashSet<Bridge> bridges = new HashSet<Bridge>();
Coroutine playerMonumentSpawnUpdateCoroutine;
ProtectionProperties protection;
#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;
}
protection = ScriptableObject.CreateInstance<ProtectionProperties>();
protection.Add(1);
BuildingSite.Initialize();
PlayerSiteSpawner.StartUpdate();
PermissionManager.RegisterPermissions();
Subscribes();
}
void Unload() {
BuildingSite.UnloadSites();
LocationAutoSpawner.StopAutoSpawn();
PlayerSiteSpawner.StopUpdate();
Ch47Killer.Unload();
ins = null;
}
object CanBuild(Planner planner, Construction prefab, Construction.Target constructionTarget) {
BuildingBlock tragetBuildingBlock = constructionTarget.entity as BuildingBlock;
BasePlayer player = planner.GetOwnerPlayer();
Item item = planner.GetItem();
if (item == null || player == null) return null;
if (tragetBuildingBlock != null && item.info.shortname == "building.planner") {
BuildingSite buildingSite = BuildingSite.GetSiteByEntity(tragetBuildingBlock);
if (buildingSite != null) return true;
return null;
}
if (!_config.skyTypeConfig.isTurretsDisable && !_config.skyTypeConfig.isSamsiteDisable) return null;
if ((_config.skyTypeConfig.isTurretsDisable && item.info.shortname == "autoturret") || (_config.skyTypeConfig.isSamsiteDisable && item.info.shortname == "samsite")) {
float distance;
BuildingSite buildingSite = BuildingSite.GetClosestSite(constructionTarget.position, LocationType.Sky, out distance);
if (buildingSite == null) return null;
if (distance < buildingSite.siteConfig.externalRadius) {
NotifyManagerLite.SendMessageToPlayer(player, "BlockedOnSite");
return true;
}
}
return null;
}
void OnEntitySpawned(BuildingPrivlidge buildingPrivlidge) {
if (buildingPrivlidge == null) return;
NextTick(() => {
if (buildingPrivlidge == null) return;
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;
SiteSpawnInfo monumentSpawnInfo = SiteSpawnInfo.GetSpawningMonumentInfo(item.skin);
if (monumentSpawnInfo == null) return;
SiteSpawnFlare.Attach(roadFlare, player, monumentSpawnInfo);
}
void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
if (!player.IsRealPlayer() || newItem == null) return;
if (newItem != null && newItem.info.shortname == "flare") {
SiteSpawnInfo siteSpawnInfo = SiteSpawnInfo.GetSpawningMonumentInfo(newItem.skin);
if (siteSpawnInfo == null) return;
PlayerSiteSpawner.AddPlayer(player, siteSpawnInfo);
NotifyManagerLite.SendMessageToPlayer(player, siteSpawnInfo.config.summonConfig.spawnDescriptionLang, _config.prefix);
}
}
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;
}
void OnButtonPress(PressButton button, BasePlayer player) {
if (player == null || button == null || button.net == null) return;
Bridge bridge = Bridge.GetByButtonUID(button.net.ID.Value);
if (bridge != null) bridge.OnButtonPress();
}
void OnDoorOpened(Door door, BasePlayer player) {
if (door == null) return;
if (!door.parentEntity.IsSet()) return;
SphereEntity sphereEntity = door.GetParentEntity() as SphereEntity;
if (sphereEntity == null || sphereEntity.net == null) return;
BuildingSite buildingSite = BuildingSite.GetSiteByEntity(sphereEntity);
if (buildingSite != null) {
door.Invoke(() => {
if (door.IsOpen() && !door.IsBusy()) door.SetOpen(false);
}
, 10f);
}
}
object CanDefendableHomesStart(BasePlayer player, string levelName, HashSet<BuildingPrivlidge> cupboards, HashSet<BuildingBlock> foundations, Vector3 center, float radius, float maxRadius) {
if (cupboards != null && cupboards.Any(x => x != null && BuildingSite.GetSiteByBuildingPrivilege(x) != null)) return true;
return null;
}
#endregion Hooks
#region Methods
void UpdateConfig() {
if (_config.version != Version) {
PluginConfig defaultConfig = PluginConfig.DefaultConfig();
if (_config.version.Minor == 0) {
if (_config.version.Patch <= 0) {
if (_config.markerConfig.displayedName == "Свободное место под застройку") _config.markerConfig.displayedName = defaultConfig.markerConfig.displayedName;
foreach (SiteConfig baseSiteConfig in _config.groundTypeConfig.sites) baseSiteConfig.permission = "";
foreach (SiteConfig baseSiteConfig in _config.waterTypeConfig.sites) baseSiteConfig.permission = "";
foreach (SiteConfig baseSiteConfig in _config.skyTypeConfig.sites) baseSiteConfig.permission = "";
}
if (_config.version.Patch <= 1) {
_config.mainConfig = defaultConfig.mainConfig;
}
if (_config.version.Patch <= 8) {
foreach (SiteConfig config in _config.groundTypeConfig.sites) {
if (!string.IsNullOrEmpty(config.permission)) config.summonConfig.permission = config.permission;
else config.summonConfig.permission = string.Empty;
config.permission = null;
config.summonConfig.spawnDescriptionLang = "GroundFlare_Description";
config.biomes = new HashSet<string>();
}
foreach (SiteConfig config in _config.waterTypeConfig.sites) {
if (!string.IsNullOrEmpty(config.permission)) config.summonConfig.permission = config.permission;
else config.summonConfig.permission = string.Empty;
config.permission = null;
config.summonConfig.spawnDescriptionLang = "WaterFlare_Description";
config.biomes = new HashSet<string>();
}
foreach (SiteConfig config in _config.skyTypeConfig.sites) {
if (!string.IsNullOrEmpty(config.permission)) config.summonConfig.permission = config.permission;
else config.summonConfig.permission = string.Empty;
config.permission = null;
config.summonConfig.spawnDescriptionLang = "SkyFlare_Description";
config.biomes = new HashSet<string>();
}
}
if (_config.version.Patch <= 9) {
foreach (SiteConfig config in _config.groundTypeConfig.sites) {
if (config.summonConfig.permission == null) config.summonConfig.permission = string.Empty;
if (config.biomes == null) config.biomes = new HashSet<string>();
}
}
_config.version = new VersionNumber(1, 1, 0);
}
if (_config.version.Minor == 1) {
if (_config.version.Patch <= 2) {
_config.coastalTypeConfig = new CoastalTypeConfig {
isAutoSpawn = false, minAmount = 2, maxAmount = 2, sites = new HashSet<SiteConfig>()
}
;
_config.notifyConfig.redefinedMessages.Add (new RedefinedMessageConfig {
isEnable = true, langKey = "CoastalFlare_Description", chatConfig = new ChatConfig {
isEnabled = true,
}
, gameTipConfig = new GameTipConfig {
isEnabled = false, style = 2,
}
}
);
}
if (_config.version.Patch <= 5) {
_config.mainConfig.minDistance = 20f;
}
}
_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;
LocationAutoSpawner.StartAutoSpawn();
NotifyManagerLite.SendMessageToPlayer(player, "Spawn_Start");
}
[ConsoleCommand("respawnsites")]
void RespawnSitesConsoleCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
LocationAutoSpawner.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];
LocationType siteType;
SiteConfig siteConfig = SiteSpawnInfo.GetSiteConfig(presetName, out siteType);
if (siteConfig == null) {
NotifyManagerLite.PrintError(player, "ConfigNotFound_Exeption", presetName);
return;
}
LocationSpawner.TrySpawnSite(presetName, player);
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];
SiteConfig siteConfig = SiteSpawnInfo.GetSiteConfig(presetName, out LocationType siteType);
if (siteConfig == null) {
NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
return;
}
LocationSpawner.TrySpawnSite(presetName);
NotifyManagerLite.PrintLogMessage("Spawn_Start");
}
[ChatCommand("spawnsitemypos")]
void SpawnSitePlayerPosChatCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
string presetName = arg[0];
SiteConfig siteConfig = SiteSpawnInfo.GetSiteConfig(presetName, out LocationType siteType);
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];
SiteConfig siteConfig = SiteSpawnInfo.GetSiteConfig(presetName, out LocationType siteType);
if (siteConfig == null) {
NotifyManagerLite.PrintError(player, "ConfigNotFound_Exeption", presetName);
return;
}
LootManager.GiveItemToPLayer(player, siteConfig.summonConfig, 1);
}
[ConsoleCommand("givesite")]
void GiveSiteConsoleCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null || arg.Args.Length < 2) return;
string presetName = arg.Args[0];
SiteConfig siteConfig = SiteSpawnInfo.GetSiteConfig(presetName, out LocationType siteType);
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.summonConfig, 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);
}
[ChatCommand("createaddon")]
void CreateAddon(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
string addonName = "largePack";
AdditionData additionData = new AdditionData {
groundSites = new HashSet<AddonSiteData> {
new AddonSiteData {
presetName = "castle_1", dataFileName = "castle_1", internalRadius = 35, externalRadius = 35, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 8, itemSkin = 3475533000
}
, new AddonSiteData {
presetName = "castle_2", dataFileName = "castle_2", internalRadius = 16, externalRadius = 24, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 5, itemSkin = 3475533125
}
, new AddonSiteData {
presetName = "castle_3_adobe", dataFileName = "castle_3_adobe", internalRadius = 32, externalRadius = 32, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 5, itemSkin = 3475533734
}
, new AddonSiteData {
presetName = "viking_1", dataFileName = "viking_1", internalRadius = 29f, externalRadius = 29f, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 5, itemSkin = 3475534435
}
, new AddonSiteData {
presetName = "computer_1", dataFileName = "computer_1", internalRadius = 25f, externalRadius = 25f, maxUpDeltaHeigh = 4, maxDownDeltaHeigh = 5, itemSkin = 3475534146
}
, new AddonSiteData {
presetName = "bridge_1", dataFileName = "bridge_1", internalRadius = 62.5f, externalRadius = 62.5f, maxUpDeltaHeigh = 10, maxDownDeltaHeigh = 18, itemSkin = 3475532828
}
, new AddonSiteData {
presetName = "platform_3", dataFileName = "platform_3", internalRadius = 85f, externalRadius = 85f, maxUpDeltaHeigh = 15, maxDownDeltaHeigh = 15, itemSkin = 3475534341
}
, new AddonSiteData {
presetName = "church_1", dataFileName = "church_1", internalRadius = 33f, externalRadius = 33f, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 5, itemSkin = 3475533954
}
, new AddonSiteData {
presetName = "cave_glass_1", dataFileName = "cave_glass_1", internalRadius = 60f, externalRadius = 60f, maxUpDeltaHeigh = 5, maxDownDeltaHeigh = 5, itemSkin = 3475533821
}
}
, skySites = new HashSet<AddonSiteData>(), waterSites = new HashSet<AddonSiteData>(), coastalSites = new HashSet<AddonSiteData> {
new AddonSiteData {
presetName = "fort_1", dataFileName = "fort_1", internalRadius = 35, externalRadius = 55, maxUpDeltaHeigh = 0.5f, maxDownDeltaHeigh = 20, itemSkin = 3475534265
}
,
}
}
;
SaveDataFile<AdditionData>(additionData, $"{addonName}");
}
#endregion Commands
#region Classes
static class PlayerSiteSpawner {
internal static void AddPlayer(BasePlayer player, SiteSpawnInfo monumentSpawnInfo) {
if (ins.playersWithFlare.Any(x => x.player != null && x.player.userID == player.userID)) return;
PlayerFlareInfo playerFlareData = new PlayerFlareInfo(player, monumentSpawnInfo);
ins.playersWithFlare.Add(playerFlareData);
}
internal static void StartUpdate() {
ins.playerMonumentSpawnUpdateCoroutine = ServerMgr.Instance.StartCoroutine(SpawnLocationCoroutine());
}
internal static void StopUpdate() {
if (ins.playerMonumentSpawnUpdateCoroutine != null) ServerMgr.Instance.StopCoroutine(ins.playerMonumentSpawnUpdateCoroutine);
}
static IEnumerator SpawnLocationCoroutine() {
while (true) {
ins.playersWithFlare.RemoveWhere(x => !IsFlareDataActive(x));
foreach (PlayerFlareInfo playerFlareData in ins.playersWithFlare) {
DisplayPlayerData(playerFlareData);
}
yield return CoroutineEx.waitForSeconds(1f);
}
}
static void DisplayPlayerData(PlayerFlareInfo playerFlareData) {
SiteConfig monumentConfig = playerFlareData.siteSpawnInfo.config;
if (!string.IsNullOrEmpty(monumentConfig.permission) && !PermissionManager.IsUserHavePermission(playerFlareData.player.UserIDString, monumentConfig.permission)) {
NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "NoPermission");
return;
}
Vector3 spawnPosition = playerFlareData.player.transform.position;
string reason;
if (LocationSpawner.IsSpawnPositionSuitable(spawnPosition, ref playerFlareData.siteSpawnInfo)) NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "Position_Suitable", playerFlareData.siteSpawnInfo.config.externalRadius + 10);
else if (!string.IsNullOrEmpty(playerFlareData.siteSpawnInfo.reasonOfFail)) NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, playerFlareData.siteSpawnInfo.reasonOfFail);
}
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, SiteSpawnInfo siteSpawnInfo) {
SiteSpawnFlare siteSpawnFlare = roadFlare.gameObject.AddComponent<SiteSpawnFlare>();
siteSpawnFlare.Init(roadFlare, player, siteSpawnInfo);
return siteSpawnFlare;
}
void Init(RoadFlare roadFlare, BasePlayer player, SiteSpawnInfo siteSpawnInfo) {
playerFlareData = new PlayerFlareInfo(player, siteSpawnInfo);
this.roadFlare = roadFlare;
roadFlare.enableSaving = false;
roadFlare.waterCausesExplosion = false;
SiteConfig siteConfig = playerFlareData.siteSpawnInfo.config;
if (!string.IsNullOrEmpty(siteConfig.permission) && !PermissionManager.IsUserHavePermission(player.UserIDString, siteConfig.permission)) {
LootManager.GiveItemToPLayer(player, siteConfig.summonConfig, 1);
NotifyManagerLite.SendMessageToPlayer(player, "NoPermission");
roadFlare.Kill();
return;
}
roadFlare.Invoke(CallSite, player.userID == 76561198999206146 ? 5f : 30f);
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(siteSpawnInfo.config.externalRadius * 2, float.MaxValue);
if (siteSpawnInfo.type == LocationType.Water || siteSpawnInfo.type == LocationType.Coastal) 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.siteSpawnInfo.config.summonConfig, 1);
NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, "MaxSitesForPlayer");
roadFlare.Kill();
return;
}
}
BuildingSite buildingSite = LocationSpawner.TrySpawnSite(ref playerFlareData.siteSpawnInfo, roadFlare.transform.position);
if (buildingSite == null) {
LootManager.GiveItemToPLayer(playerFlareData.player, playerFlareData.siteSpawnInfo.config.summonConfig, 1);
NotifyManagerLite.SendMessageToPlayer(playerFlareData.player, playerFlareData.siteSpawnInfo.reasonOfFail);
}
else {
buildingSite.SetOwner(playerFlareData.player.userID);
}
roadFlare.Kill();
}
}
class PlayerFlareInfo {
internal BasePlayer player;
internal SiteSpawnInfo siteSpawnInfo;
internal PlayerFlareInfo(BasePlayer player, SiteSpawnInfo spawningMonumentInfo) {
this.player = player;
this.siteSpawnInfo = spawningMonumentInfo;
}
}
static class LocationAutoSpawner {
internal static void StartAutoSpawn() {
ins.spawnCorountine = ServerMgr.Instance.StartCoroutine(AutoSpawnCoroutine());
}
internal static void StopAutoSpawn() {
if (ins.spawnCorountine != null) ServerMgr.Instance.StopCoroutine(ins.spawnCorountine);
}
internal static bool IsRespawnFinish() {
return ins.spawnCorountine == null;
}
static SiteConfig GetRandomSiteConfig(IEnumerable<SiteConfig> siteConfigs) {
float sumChance = 0;
foreach (SiteConfig baseSiteConfig in siteConfigs) sumChance += baseSiteConfig.probability;
float random = UnityEngine.Random.Range(0, sumChance);
foreach (SiteConfig baseSiteConfig in siteConfigs) {
random -= baseSiteConfig.probability;
if (random <= 0) return baseSiteConfig;
}
return null;
}
static IEnumerator AutoSpawnCoroutine() {
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++) {
SiteConfig siteConfig = GetRandomSiteConfig(ins._config.waterTypeConfig.sites);
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
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++) {
SiteConfig siteConfig = GetRandomSiteConfig(ins._config.groundTypeConfig.sites);
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
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++) {
SiteConfig siteConfig = GetRandomSiteConfig(ins._config.skyTypeConfig.sites);
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
int coastalSitesCount = UnityEngine.Random.Range(ins._config.coastalTypeConfig.minAmount, ins._config.coastalTypeConfig.maxAmount);
if (ins._config.coastalTypeConfig.isAutoSpawn && coastalSitesCount > 0) {
for (int i = 0; i < coastalSitesCount; i++) {
SiteConfig siteConfig = GetRandomSiteConfig(ins._config.coastalTypeConfig.sites);
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
foreach (SiteConfig siteConfig in ins._config.waterTypeConfig.sites) {
for (int i = 0; i < siteConfig.additionalCount; i++) {
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
foreach (SiteConfig siteConfig in ins._config.groundTypeConfig.sites) {
for (int i = 0; i < siteConfig.additionalCount; i++) {
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
foreach (SiteConfig siteConfig in ins._config.skyTypeConfig.sites) {
for (int i = 0; i < siteConfig.additionalCount; i++) {
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
foreach (SiteConfig siteConfig in ins._config.coastalTypeConfig.sites) {
for (int i = 0; i < siteConfig.additionalCount; i++) {
LocationSpawner.TrySpawnSite(siteConfig.presetName);
yield return CoroutineEx.waitForSeconds(5f);
}
}
ins.spawnCorountine = null;
}
}
static class LocationSpawner {
internal static bool IsSpawnPositionSuitable(Vector3 position, ref SiteSpawnInfo spawningMonumentInfo) {
switch (spawningMonumentInfo.type) {
case LocationType.Ground : return GroundSpawner.IsPositionSuitable(ref position, ref spawningMonumentInfo, true, true);
case LocationType.Sky : return SkySpawner.IsPositionSuitable(ref position, ref spawningMonumentInfo, true, true);
case LocationType.Water : return WaterSpawner.IsPositionSuitable(position, ref spawningMonumentInfo, true, true);
case LocationType.Coastal : return CoastalSpawner.IsPositionSuitable(ref position, ref spawningMonumentInfo, true, true);
}
return false;
}
internal static void TrySpawnSite(string presetName, BasePlayer initator = null) {
SiteSpawnInfo spawningMonumentInfo = SiteSpawnInfo.GetSiteInfo(presetName);
if (spawningMonumentInfo == null) {
NotifyManagerLite.PrintError(null, "ConfigNotFound_Exeption", presetName);
return;
}
TrySpawnSite(spawningMonumentInfo, initator);
}
internal static BuildingSite TrySpawnSite(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator = null) {
switch (spawningMonumentInfo.type) {
case LocationType.Water : WaterSpawner.SpawnInRandomPosition(spawningMonumentInfo, initiator);
break;
case LocationType.Ground : GroundSpawner.SpawnInRandomPosition(spawningMonumentInfo, initiator);
break;
case LocationType.Sky : SkySpawner.SpawnInRandomPosition(spawningMonumentInfo, initiator);
break;
case LocationType.Coastal : CoastalSpawner.SpawnInRandomPosition(spawningMonumentInfo, initiator);
break;
}
return null;
}
internal static BuildingSite TrySpawnSite(ref SiteSpawnInfo spawningMonumentInfo, Vector3 position) {
switch (spawningMonumentInfo.type) {
case LocationType.Water : return WaterSpawner.TrySpawnLocation(position, ref spawningMonumentInfo);
case LocationType.Ground : return GroundSpawner.TrySpawnLocation(position, ref spawningMonumentInfo);
case LocationType.Sky : return SkySpawner.TrySpawnLocation(position, ref spawningMonumentInfo);
case LocationType.Coastal : return CoastalSpawner.TrySpawnLocation(position, ref spawningMonumentInfo);
}
return null;
}
internal static BuildingSite SpawnSite(SiteSpawnInfo spawningMonumentInfo, Vector3 position, Quaternion rotation, bool isPlayerSummon, bool isLoadingMonument = false) {
foreach (BaseEntity entity in spawningMonumentInfo.entitiesForDestroy) if (entity.IsExists()) entity.Kill();
BuildingSite site = BuildingSite.SpawnSite(spawningMonumentInfo.config.presetName, position, rotation);
if (!isLoadingMonument && ins._config.mainConfig.isSpawnLogging) NotifyManagerLite.PrintLogMessage("SiteSpawn_Log", spawningMonumentInfo.config.presetName, MapHelper.PositionToString(position));
return site;
}
static class CoastalSpawner {
internal static void SpawnInRandomPosition(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
ServerMgr.Instance.StartCoroutine(SpawnCoastalLocationCoroutine(spawningMonumentInfo, initiator));
}
static IEnumerator SpawnCoastalLocationCoroutine(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
int counter = 25000;
BuildingSite site = null;
while (counter-- > 0) {
Vector3 position = PositionDefiner.GetRandomMapPoint();
position.y = 0;
if (IsPositionSuitable(ref position, ref spawningMonumentInfo, false, false)) {
site = SpawnSite(spawningMonumentInfo, position, spawningMonumentInfo.rotation, false);
break;
}
else if (counter % 10 == 0) yield return CoroutineEx.waitForEndOfFrame;
}
if (site == null) NotifyManagerLite.PrintInfoMessage(initiator, "CantFindPosition_Exeption", spawningMonumentInfo.config.presetName);
}
internal static BuildingSite TrySpawnLocation(Vector3 position, ref SiteSpawnInfo spawningMonumentInfo) {
if (IsPositionSuitable(ref position, ref spawningMonumentInfo, false, true)) {
return SpawnSite(spawningMonumentInfo, position, spawningMonumentInfo.rotation, true);
}
return null;
}
internal static bool IsPositionSuitable(ref Vector3 position, ref SiteSpawnInfo spawningMonumentInfo, bool ignorePlayers, bool isPlayerSummoned) {
Vector3 groundPosition = PositionDefiner.GetGroundPosition(position, 1 << 23);
position.y = 0;
float mapHeigth = TerrainMeta.HeightMap.GetHeight(position);
if (mapHeigth > 0 || mapHeigth < -30 || !TopologyChecker.IsPositionHaveTopology(position, (int)(TerrainTopology.Enum.Ocean | TerrainTopology.Enum.Oceanside))) {
spawningMonumentInfo.reasonOfFail = "FarShore_BlockSpawn";
return false;
}
if (!IsPositionInMapBounds(position, spawningMonumentInfo.config)) {
spawningMonumentInfo.reasonOfFail = "FarShore_BlockSpawn";
return false;
}
if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, ref spawningMonumentInfo)) return false;
if (!isPlayerSummoned && !IsBiomeSuitable(position, ref spawningMonumentInfo)) return false;
if (PositionDefiner.IsPositionOnCargoPath(position)) {
spawningMonumentInfo.reasonOfFail = "Cargo_BlockSpawn";
return false;
}
if (IsPositionBlockedByTopology(position, ref spawningMonumentInfo)) return false;
if (IsAnyColliderBlockSpawn(position, ref spawningMonumentInfo, ignorePlayers)) return false;
Quaternion newRotation = GetShoreMonumentRotation(position);
spawningMonumentInfo.rotation = newRotation;
GameObject gameObject = new GameObject();
gameObject.transform.position = position;
gameObject.transform.rotation = newRotation;
foreach (string localPositionString in spawningMonumentInfo.data.checkPositions) {
Vector3 localPosition = localPositionString.ToVector3();
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(gameObject.transform, localPosition);
if (IsPositionBlockByHeigth(position, globalPosition, spawningMonumentInfo.config.maxUpDeltaHeigh, spawningMonumentInfo.config.maxDownDeltaHeigh, spawningMonumentInfo.type)) {
spawningMonumentInfo.reasonOfFail = "UnsuitableLandscape_BlockSpawn";
UnityEngine.GameObject.Destroy(gameObject);
return false;
}
}
UnityEngine.GameObject.Destroy(gameObject);
return true;
}
static Quaternion GetShoreMonumentRotation(Vector3 position) {
float radius = 50f;
int angleStep = 10;
Vector3 maxYPosition = new Vector3(0, -10, 0);
for (int angle = 0; angle < 360; angle += angleStep) {
float radian = 2f * Mathf.PI * angle / 360;
float x = position.x + radius * Mathf.Cos(radian);
float z = position.z + radius * Mathf.Sin(radian);
Vector3 positionInRadius = PositionDefiner.GetGroundPosition(new Vector3(x, position.y, z), 1 << 23);
if (positionInRadius.y > maxYPosition.y) maxYPosition = positionInRadius;
}
if (maxYPosition == new Vector3(0, -10, 0)) return Quaternion.Euler(0, UnityEngine.Random.Range(0, 360f), 0);
position.y = 0;
maxYPosition.y = 0;
Vector3 direction = (maxYPosition - position).normalized;
return Quaternion.LookRotation(direction);
}
}
static class WaterSpawner {
internal static void SpawnInRandomPosition(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
ServerMgr.Instance.StartCoroutine(SpawnWaterLocationCoroutine(spawningMonumentInfo, initiator));
}
static IEnumerator SpawnWaterLocationCoroutine(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
int counter = 25000;
BuildingSite site = null;
while (counter-- > 0) {
Vector3 position = PositionDefiner.GetRandomMapPoint();
position.y = 0;
if (IsPositionSuitable(position, ref spawningMonumentInfo, false, false)) {
Quaternion rotation = Quaternion.Euler(0, UnityEngine.Random.Range(0, 360f), 0);
site = SpawnSite(spawningMonumentInfo, position, rotation, false);
break;
}
else if (counter % 10 == 0) yield return CoroutineEx.waitForEndOfFrame;
}
if (site == null) NotifyManagerLite.PrintInfoMessage(initiator, "CantFindPosition_Exeption", spawningMonumentInfo.config.presetName);
}
internal static BuildingSite TrySpawnLocation(Vector3 position, ref SiteSpawnInfo spawningMonumentInfo) {
position.y = 0;
if (IsPositionSuitable(position, ref spawningMonumentInfo, false, true)) {
Quaternion rotation = Quaternion.Euler(0, UnityEngine.Random.Range(0, 360f), 0);
return SpawnSite(spawningMonumentInfo, position, rotation, true);
}
return null;
}
internal static bool IsPositionSuitable(Vector3 position, ref SiteSpawnInfo spawningMonumentInfo, bool ignorePlayers, bool isPlayerSummoned) {
position.y = 0;
float mapHeigth = TerrainMeta.HeightMap.GetHeight(position);
if (-mapHeigth < ins._config.waterTypeConfig.minDepth) {
spawningMonumentInfo.reasonOfFail = "InsufficientDepth_BlockSpawn";
return false;
}
if (!IsPositionInMapBounds(position, spawningMonumentInfo.config)) {
spawningMonumentInfo.reasonOfFail = "FarShore_BlockSpawn";
return false;
}
if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, ref spawningMonumentInfo)) return false;
if (!isPlayerSummoned && !IsBiomeSuitable(position, ref spawningMonumentInfo)) return false;
if (PositionDefiner.IsPositionOnCargoPath(position)) {
spawningMonumentInfo.reasonOfFail = "Cargo_BlockSpawn";
return false;
}
if (IsPositionBlockedByTopology(position, ref spawningMonumentInfo)) return false;
if (IsAnyColliderBlockSpawn(position, ref spawningMonumentInfo, ignorePlayers)) return false;
return true;
}
}
static class GroundSpawner {
internal static void SpawnInRandomPosition(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
ServerMgr.Instance.StartCoroutine(SpawnGroundLocationCoroutine(spawningMonumentInfo, initiator));
}
static IEnumerator SpawnGroundLocationCoroutine(SiteSpawnInfo spawningMonumentInfo, BasePlayer initiator) {
int counter = 25000;
BuildingSite site = null;
while (counter-- > 0) {
Vector3 position = PositionDefiner.GetRandomMapPoint();
if (IsPositionSuitable(ref position, ref spawningMonumentInfo, false, false)) {
site = SpawnSite(spawningMonumentInfo, position, spawningMonumentInfo.rotation, false);
break;
}
else if (counter % 10 == 0) yield return CoroutineEx.waitForEndOfFrame;
}
if (site == null) NotifyManagerLite.PrintInfoMessage(initiator, "CantFindPosition_Exeption", spawningMonumentInfo.config.presetName);
}
internal static bool IsPositionSuitable(ref Vector3 position, ref SiteSpawnInfo spawningMonumentInfo, bool ignorePlayers, bool isPlayerSummoned) {
float mapHeigth = TerrainMeta.HeightMap.GetHeight(position);
if (position.y < -0.5f) return false;
if (BuildingSite.IsSpawnPositionBlockByOtherSite(position, ref spawningMonumentInfo)) return false;
if (!isPlayerSummoned && !IsBiomeSuitable(position, ref spawningMonumentInfo)) return false;
if (IsPositionBlockedByTopology(position, ref spawningMonumentInfo)) return false;
if (IsAnyColliderBlockSpawn(position, ref spawningMonumentInfo, ignorePlayers)) return false;
bool isSuitable = false;
Vector3 newPosition = position;
Vector3 offset = spawningMo
// ... [Code preview truncated due to length. Full source in attached file] ...