C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using CompanionServer.Handlers;
using Facepunch;
using Network;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins.BargesExtensionMethods;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;
using static StabilityEntity;
namespace Oxide.Plugins {
[Info("Barges", "Adem", "1.0.9")]
class Barges : RustPlugin {
#region Variables
const bool en = true;
static Barges ins;
[PluginReference]
Plugin GUIAnnouncements, Notify, DiscordMessages;
HashSet<string> subscribeMethods = new HashSet<string> {
"OnButtonPress", "CanBuild", "CanPickupEntity", "CanChangeGrade", "OnStructureRotate", "OnStructureUpgraded", "OnConstructionPlace", "OnPoweredLightsPointAdd", "OnEntityStabilityCheck", "OnEntityKill", "OnEntitySpawned", "CanMountEntity", "OnEntityMounted", "OnHammerHit", "CanPickupEntity", "OnWireClear", "OnWireConnect", "OnExplosiveThrown", "OnEntityTakeDamage", "CanLootEntity", "CanEntityTakeDamage", "OnSetupTurret"
}
;
#endregion Variables
#region Hooks
void Init() {
Unsubscribes();
}
void OnServerInitialized() {
ins = this;
UpdateConfig();
if (!TryLoadData()) {
NotifyManager.PrintError(null, "DataNotFound_Exeption");
NextTick(() => Interface.Oxide.UnloadPlugin(Name));
return;
}
LoadDefaultMessages();
Subscribes();
BoatConnectionTrigger.UpdateAllBoats();
FishingVilageZoneController.CacheVilages();
CargoShipManager.UpdateAllCargos();
Barge.LoadBarges();
BargeSpawner.StartPeriodicSpawn();
}
void Unload() {
if (ins == null) return;
Barge.SaveBarges(true);
Barge.UnloadBarges();
BargeSpawner.StopSpawning();
BoatConnectionTrigger.Unload();
FishingVilageZoneController.ClearZones();
CargoShipManager.Unload();
AdaptorInstallController.OnPluginUnload();
ins = null;
}
void OnServerSave() {
Barge.SaveBarges();
}
void OnButtonPress(PressButton button, BasePlayer player) {
if (player == null || button == null) return;
Barge barge = Barge.GetBargeByEntity(button);
if (barge == null) return;
BaseEntity parentEntity = button.GetParentEntity();
if (parentEntity == null) return;
BaseModule baseModule = parentEntity.GetComponentInChildren<BaseModule>();
if (baseModule == null || !barge.IsPlayerCanInterract(player, true)) return;
baseModule.OnButtonPressed(player);
}
object OnPlayerCommand(BasePlayer player, string command, string[] args) {
if (player == null) return null;
string checkClommand = command;
foreach (string arg in args) checkClommand += $" {arg}";
if (_config.mainConfig.blockedCommands.Any(x => x.ToLower() == checkClommand.ToLower())) {
Barge barge = Barge.GetBargeByCollider(player);
if (barge == null) return null;
NotifyManager.SendMessageToPlayer(player, "BlockedOnBarge");
return true;
}
return null;
}
object CanBuild(Planner planner, Construction prefab, Construction.Target constructionTarget) {
if (planner == null || constructionTarget.entity == null) return null;
BasePlayer player = planner.GetOwnerPlayer();
if (player == null) return null;
BaseEntity parentEntity = constructionTarget.entity.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return null;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) {
if (Barge.GetBargeByEntity(parentEntity)) return true;
return null;
}
Item item = planner.GetItem();
if (item != null && item.info != null && _config.mainConfig.bloskedItemShortnames.Contains(item.info.shortname)) {
NotifyManager.SendMessageToPlayer(player, "BlockedOnBarge");
return true;
}
if (!barge.IsPlayerCanInterract(player, true)) return true;
if (planner.ShortPrefabName.Contains("wallpaper") || (prefab != null && prefab.deployable != null && (prefab.deployable.fullName.Contains("frankensteintable")))) {
//|| prefab.deployable.fullName.Contains("electrical.modularcarlift.deployed")
NotifyManager.SendMessageToPlayer(player, "BlockedOnBarge");
return true;
}
if (!barge.IsPlayerCanBuild(player, true)) return true;
return null;
}
object CanPickupEntity(BasePlayer player, BaseEntity entity) {
if (player == null || entity == null) return null;
Barge barge = Barge.GetBargeByEntity(entity);
if (barge == null) {
BuildingPrivlidge buildingPrivlidge = player.GetBuildingPrivilege();
if (buildingPrivlidge != null && Barge.GetBargeByEntity(buildingPrivlidge) != null) {
BuildingPrivlidge entityBuildingPrivlidge = entity.GetBuildingPrivilege();
if (entityBuildingPrivlidge != null && !entityBuildingPrivlidge.IsAuthed(player)) return false;
}
return null;
}
if (!barge.IsPlayerCanInterract(player, false)) return false;
return null;
}
object CanChangeGrade(BasePlayer player, BuildingBlock block, BuildingGrade.Enum grade) {
if (player == null) return null;
Barge barge = Barge.GetBargeByEntity(block);
if (barge == null) return null;
if (!barge.IsPlayerCanBuild(player, true)) return false;
if (block.grade == grade && _config.performanceConfig.autoSkin) return false;
if (barge.IsBasicBuildingBlock(block)) return false;
if ((!ins._config.performanceConfig.allowStone && grade == BuildingGrade.Enum.Stone) || (!ins._config.performanceConfig.allowHqm && grade == BuildingGrade.Enum.TopTier)) {
NotifyManager.SendMessageToPlayer(player, "BlockGrade");
return false;
}
else if ((!ins._config.performanceConfig.allowMetall && grade == BuildingGrade.Enum.Metal) || (!ins._config.performanceConfig.allowWood && grade == BuildingGrade.Enum.Wood)) {
return false;
}
return null;
}
object OnStructureRotate(BaseCombatEntity entity, BasePlayer player) {
if (entity == null) return null;
Barge barge = Barge.GetBargeByEntity(entity);
if (barge == null) return null;
if (!barge.IsStopped()) {
NotifyManager.SendMessageToPlayer(player, "AnchorBarge");
return true;
}
return null;
}
void OnStructureUpgraded(BuildingBlock buildingBlock, BasePlayer player, BuildingGrade.Enum grade, ulong skin) {
if (buildingBlock == null) return;
Barge barge = Barge.GetBargeByEntity(buildingBlock);
if (barge == null) return;
if (!_config.performanceConfig.autoSkin) return;
if (grade == BuildingGrade.Enum.Wood && skin != 10232) {
buildingBlock.ChangeGradeAndSkin(BuildingGrade.Enum.Wood, 10232, true);
}
else if (grade == BuildingGrade.Enum.Metal && skin != 10221) {
buildingBlock.ChangeGradeAndSkin(BuildingGrade.Enum.Metal, 10221, true);
buildingBlock.SetCustomColour(11);
}
}
void OnConstructionPlace(BaseCombatEntity entity, Construction component, Construction.Target constructionTarget, BasePlayer player) {
if (entity == null || constructionTarget.entity == null || player == null) return;
BaseEntity parentEntity = constructionTarget.entity.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return;
Barge barge = Barge.GetBargeByParentEntityNetId(parentEntity.net.ID.Value);
if (barge == null) return;
barge.OnPlayerBuild(player, entity, constructionTarget.entity);
}
object OnPoweredLightsPointAdd(PoweredLightsDeployer poweredLightsDeployer, BasePlayer player, Vector3 vector31, Vector3 vector32) {
if (player == null) return null;
Barge barge = Barge.GetBargeByCollider(player);
if (barge == null) return null;
NotifyManager.SendMessageToPlayer(player, "BlockedOnBarge");
return true;
}
object OnEntityStabilityCheck(BuildingBlock buildingBlock) {
if (buildingBlock == null || buildingBlock.net == null) return null;
Barge barge = Barge.GetBargeByEntity(buildingBlock);
if (barge == null) return null;
return true;
}
void OnEntityKill(BuildingBlock buildingBlock) {
if (buildingBlock == null || buildingBlock.net == null) return;
Barge barge = Barge.GetBargeByEntity(buildingBlock);
if (barge == null) return;
barge.Invoke(() => barge.shoudUpdateStability = true, 0.1f);
}
object OnEntityKill(SkyLantern skyLantern) {
if (skyLantern == null || skyLantern.net == null) return null;
Barge barge = Barge.GetBargeByParentEntityNetId(skyLantern.net.ID.Value);
if (barge == null) return null;
if (!barge.shoudKill) return true;
return null;
}
void OnEntitySpawned(BaseBoat baseBoat) {
if (baseBoat == null) return;
BoatConnectionTrigger.TryAddBoatConnectionTrigger(baseBoat);
}
void OnEntitySpawned(CargoShip cargoShip) {
if (cargoShip == null) return;
CargoShipManager.AttachController(cargoShip);
}
void OnEntitySpawned(DecayEntity decayEntity) {
CheckIfOtherPluginSpawnedEntity(decayEntity);
}
void OnEntitySpawned(Recycler recycler) {
CheckIfOtherPluginSpawnedEntity(recycler);
}
void OnEntitySpawned(BasePortal basePortal) {
CheckIfOtherPluginSpawnedEntity(basePortal);
}
void CheckIfOtherPluginSpawnedEntity(BaseEntity baseEntity) {
if (baseEntity == null || baseEntity.HasParent()) return;
if (baseEntity is StorageContainer && !baseEntity.enableSaving) return;
Barge barge = Barge.GetBargeByCollider(baseEntity);
if (barge == null) return;
if (!barge.IsEntityShoudParrent(baseEntity) || barge.IsEntityShoutParentToTargetEntity(baseEntity)) return;
baseEntity.SetParent(barge.mainEntity, true);
}
object CanMountEntity(BasePlayer player, BaseMountable baseMountable) {
if (player == null || baseMountable == null) return null;
if ((baseMountable is BaseVehicleSeat && baseMountable.ShortPrefabName != "arcadeuser") || baseMountable is MovableBaseMountable) return null;
Barge barge = Barge.GetBargeByEntity(baseMountable);
if (barge == null) {
BaseEntity parentEntity = baseMountable.VehicleParent();
if (parentEntity == null) return null;
barge = Barge.GetBargeByEntity(parentEntity);
}
if (barge == null) return null;
if (!barge.IsStopped()) {
NotifyManager.SendMessageToPlayer(player, "BlockedWhileMoving");
return true;
}
return null;
}
void OnEntityMounted(BaseMountable baseMountable, BasePlayer player) {
if (baseMountable == null || player == null) return;
BaseVehicle baseVehicle = baseMountable.VehicleParent();
if (baseVehicle == null || !baseVehicle.IsDriver(player)) return;
if (baseVehicle is not BaseBoat && baseVehicle is not BaseSubmarine) return;
BaseEntity parentEntity = baseVehicle.GetParentEntity();
if (parentEntity == null) return;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) return;
DockModule dockModule = parentEntity.GetComponentInChildren<DockModule>();
if (dockModule == null || !barge.IsPlayerCanInterract(player, true)) return;
dockModule.ReleaseBoat();
}
void OnHammerHit(BasePlayer player, HitInfo info) {
if (player == null || info == null || info.HitEntity == null) return;
if (info.HitEntity.ShortPrefabName != "coaling_tower_fuel_storage.entity") return;
Barge barge = Barge.GetBargeByEntity(info.HitEntity);
if (barge == null || barge.IsStopped()) return;
BargePhysics bargePhysics = barge.GetBargePhysics();
Vector3 pushDirection = (barge.transform.position - player.transform.position).normalized;
pushDirection.y = 0;
if (!barge.IsBargeOnShoal()) return;
if (TerrainMeta.HeightMap.GetHeight(barge.transform.position + pushDirection) > TerrainMeta.HeightMap.GetHeight(barge.transform.position)) return;
barge.StartMoving();
bargePhysics.PushBarge(pushDirection);
}
object CanPickupEntity(BasePlayer player, SimpleLight simpleLight) {
if (simpleLight == null || simpleLight.net == null) return null;
Barge barge = Barge.GetBargeByEntity(simpleLight);
if (barge == null) return null;
if (simpleLight.GetParentEntity() is not DoorCloser) return null;
return false;
}
object CanPickupEntity(BasePlayer player, PressButton preseButton) {
if (preseButton == null) return null;
if (preseButton.HasFlag(BaseEntity.Flags.InUse)) return false;
return true;
}
object OnWireClear(BasePlayer player, IOEntity entity1, int connected, IOEntity entity2, bool flag) {
if (entity1 == null || entity2 == null) return null;
Barge barge = Barge.GetBargeByEntity(entity1);
if (barge == null) barge = Barge.GetBargeByEntity(entity2);
if (barge == null) return null;
if (!barge.IsStopped()) {
NotifyManager.SendMessageToPlayer(player, "BlockedWhileMoving");
return true;
}
return null;
}
object OnWireConnect(BasePlayer player, IOEntity entity1, int inputs, IOEntity entity2, int outputs) {
if (entity1 == null || entity2 == null) return null;
Barge barge1 = Barge.GetBargeByEntity(entity1);
Barge barge2 = Barge.GetBargeByEntity(entity2);
if (barge1 != barge2) return true;
if (barge1 == null) return null;
if (!barge1.IsStopped()) {
NotifyManager.SendMessageToPlayer(player, "BlockedWhileMoving");
return true;
}
return null;
}
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;
BargeConfig bargeConfig = _config.bargeConfigs.FirstOrDefault(x => x.itemConfig.shortname == item.info.shortname && x.itemConfig.skin == item.skin);
if (bargeConfig == null) return;
BargeCaller.Attach(roadFlare, player, bargeConfig);
}
object OnEntityTakeDamage(SkyLantern skyLantern, HitInfo info) {
if (skyLantern == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(skyLantern);
if (barge == null) return null;
return true;
}
object OnEntityTakeDamage(BuildingBlock buildingBlock, HitInfo info) {
if (buildingBlock == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(buildingBlock);
if (barge == null) return null;
if (barge.IsBasicBuildingBlock(buildingBlock)) return true;
return null;
}
object OnEntityTakeDamage(PressButton button, HitInfo info) {
if (button == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(button);
if (barge == null) return null;
BaseEntity parentEntity = button.GetParentEntity();
if (parentEntity == null) return null;
BaseModule baseModule = parentEntity.GetComponentInChildren<BaseModule>();
if (baseModule == null) return null;
return true;
}
object OnEntityTakeDamage(BaseBoat baseBoat, HitInfo info) {
if (baseBoat == null || info == null) return null;
BaseEntity parentEntity = baseBoat.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return null;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) return null;
if (info.damageTypes.GetMajorityDamageType() == DamageType.Decay) return true;
return null;
}
object OnEntityTakeDamage(BaseSubmarine baseSubmarine, HitInfo info) {
if (baseSubmarine == null || info == null) return null;
BaseEntity parentEntity = baseSubmarine.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return null;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) return null;
if (info.damageTypes.GetMajorityDamageType() == DamageType.Decay) return true;
return null;
}
object CanLootEntity(BasePlayer player, ResourceExtractorFuelStorage container) {
if (container == null || player == null) return null;
Barge barge = Barge.GetBargeByEntity(container);
if (barge == null) return null;
if (container.GetParentEntity() is DoorCloser && !barge.IsPlayerCanInterract(player, true)) return true;
return null;
}
void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem) {
if (!player.IsRealPlayer() || newItem == null) return;
if (newItem.info.shortname == "storageadaptor") AdaptorInstallController.TryAttachController(player);
}
object CanEntityTakeDamage(SkyLantern skyLantern, HitInfo info) {
if (skyLantern == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(skyLantern);
if (barge == null) return null;
return false;
}
object CanEntityTakeDamage(BuildingBlock buildingBlock, HitInfo info) {
if (buildingBlock == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(buildingBlock);
if (barge == null) return null;
if (barge.IsBasicBuildingBlock(buildingBlock)) return false;
return null;
}
object CanEntityTakeDamage(PressButton button, HitInfo info) {
if (button == null || info == null) return null;
Barge barge = Barge.GetBargeByEntity(button);
if (barge == null) return null;
BaseEntity parentEntity = button.GetParentEntity();
if (parentEntity == null) return null;
BaseModule baseModule = parentEntity.GetComponentInChildren<BaseModule>();
if (baseModule == null) return null;
return false;
}
object CanEntityTakeDamage(BaseBoat baseBoat, HitInfo info) {
if (baseBoat == null || info == null) return null;
BaseEntity parentEntity = baseBoat.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return null;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) return null;
if (info.damageTypes.GetMajorityDamageType() == DamageType.Decay) return false;
return null;
}
object CanEntityTakeDamage(BaseSubmarine baseSubmarine, HitInfo info) {
if (baseSubmarine == null || info == null) return null;
BaseEntity parentEntity = baseSubmarine.GetParentEntity();
if (parentEntity == null || parentEntity.net == null) return null;
Barge barge = Barge.GetBargeByEntity(parentEntity);
if (barge == null) return null;
if (info.damageTypes.GetMajorityDamageType() == DamageType.Decay) return false;
return null;
}
object OnSetupTurret(AutoTurret autoTurret) {
if (autoTurret == null || autoTurret.net == null) return null;
if (Barge.GetBargeByEntity(autoTurret) != null) return true;
return null;
}
object OnSetupTurret(SamSite samSite) {
if (samSite == null || samSite.net == null) return null;
if (Barge.GetBargeByEntity(samSite) != null) return true;
return null;
}
#endregion Hooks
#region Commands
[ChatCommand("spawnbarge")]
void ChatSpawnBargeCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
string bargePreset = "";
if (arg.Length > 0) bargePreset = arg[0];
Barge.SpawnBarge(player.transform.position, Quaternion.identity, bargePreset, false);
}
[ChatCommand("killbarge")]
void ChatKillCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
BaseEntity target = RaycastAll<BaseEntity>(player.eyes.HeadRay());
if (target == null) return;
Barge barge = Barge.GetBargeByEntity(target);
if (barge == null) return;
barge.KillBarge();
}
[ChatCommand("killallbarges")]
void ChatKillAllCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
Barge.KillAllBarges();
}
[ChatCommand("bargetest")]
void ChatTestCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
}
[ChatCommand("givebarge")]
void ChatGiveBargeCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin || arg.Length < 1) return;
string presetName = arg[0];
BargeConfig bargeConfig = _config.bargeConfigs.FirstOrDefault(x => x.presetName == presetName);
if (bargeConfig == null) {
NotifyManager.PrintError(player, "ConfigNotFound_Exeption", presetName);
return;
}
LootManager.GiveItemToPLayer(player, bargeConfig.itemConfig, 1);
NotifyManager.SendMessageToPlayer(player, "GotBarge");
}
[ConsoleCommand("givebarge")]
void ConsoleGiveBargeCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null || arg.Args.Length < 2) return;
string presetName = arg.Args[0];
BargeConfig bargeConfig = _config.bargeConfigs.FirstOrDefault(x => x.presetName == presetName);
if (bargeConfig == null) {
NotifyManager.PrintError(null, "ConfigNotFound_Exeption", presetName);
return;
}
ulong targetUserId = Convert.ToUInt64(arg.Args[1]);
BasePlayer targetPlayer = BasePlayer.FindByID(targetUserId);
if (targetPlayer == null) {
NotifyManager.PrintError(null, "PlayerNotFound_Exeption", arg.Args[1]);
return;
}
LootManager.GiveItemToPLayer(targetPlayer, bargeConfig.itemConfig, 1);
NotifyManager.SendMessageToPlayer(targetPlayer, "GotBarge");
}
[ConsoleCommand("savebarge")]
void ConsoleSaveBargeCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
MapSaver.CreateOrAddNewData("new");
}
#endregion Commands
#region Methods
void UpdateConfig() {
if (_config.version != Version) {
PluginConfig defaultConfig = PluginConfig.DefaultConfig();
if (_config.version.Patch <= 1) {
foreach (BargeConfig bargeConfig in _config.bargeConfigs) {
bargeConfig.engineConfig.rotateScale = 1f;
}
}
if (_config.version.Patch <= 4) {
_config.mainConfig.blockedCommands = defaultConfig.mainConfig.blockedCommands;
}
if (_config.version.Patch <= 8) {
_config.performanceConfig.dontAnchorIfConnected = true;
_config.performanceConfig.anchorTime = 300;
}
_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);
}
BaseEntity RaycastAll<T>(Ray ray, float distance = 50) where T : BaseEntity {
RaycastHit[] hits = Physics.RaycastAll(ray);
GamePhysics.Sort(hits);
BaseEntity target = null;
foreach (RaycastHit hit in hits) {
BaseEntity ent = hit.GetEntity();
if (ent is T && hit.distance < distance) {
target = ent;
break;
}
}
return target;
}
#endregion Methods
#region Classes
static class BargeSpawner {
static Coroutine spawnCorountine;
static HashSet<SpawnPositionInfo> spawnLocations = new HashSet<SpawnPositionInfo>();
internal static void StartPeriodicSpawn() {
if (!ins._config.spawnConfig.isSpawnEnabled) return;
CacheSuitableMonuments();
if (spawnLocations.Count == 0) return;
spawnCorountine = ServerMgr.Instance.StartCoroutine(SpawnCorountine());
}
static void CacheSuitableMonuments() {
spawnLocations = new HashSet<SpawnPositionInfo>();
foreach (MonumentInfo monumentInfo in TerrainMeta.Path.Monuments) {
if (monumentInfo == null || monumentInfo.transform == null) continue;
SpawnMonumentConfig spawnMonumentConfig = ins._config.spawnConfig.monuments.FirstOrDefault(x => x.isEnabled && x.monumentName == monumentInfo.name);
if (spawnMonumentConfig == null) continue;
SaveMonumentPositions(monumentInfo, spawnMonumentConfig);
}
}
static void SaveMonumentPositions(MonumentInfo monumentInfo, SpawnMonumentConfig spawnMonumentConfig) {
foreach (LocationConfig locationConfig in spawnMonumentConfig.locations) {
Vector3 localPosition = locationConfig.position.ToVector3();
Vector3 localRotation = locationConfig.rotation.ToVector3();
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(monumentInfo.transform, localPosition);
Quaternion globalRotation = PositionDefiner.GetGlobalRotation(monumentInfo.transform, localRotation);
SpawnPositionInfo spawnPositionInfo = new SpawnPositionInfo(globalPosition, globalRotation);
spawnLocations.Add(spawnPositionInfo);
}
}
static IEnumerator SpawnCorountine() {
while (true) {
yield return CoroutineEx.waitForSeconds(UnityEngine.Random.Range(ins._config.spawnConfig.minSpawnTime, ins._config.spawnConfig.maxSpawnTime));
List<SpawnPositionInfo> suitablePositions = Pool.Get<List<SpawnPositionInfo>>();
foreach (SpawnPositionInfo suitablePosition in spawnLocations) if (IsPositionSuitable(suitablePosition.position)) suitablePositions.Add(suitablePosition);
if (suitablePositions.Count > 0) {
SpawnPositionInfo spawnPositionInfo = suitablePositions.GetRandom();
SpawnBarge(spawnPositionInfo);
}
Pool.FreeUnmanaged(ref suitablePositions);
}
}
static void SpawnBarge(SpawnPositionInfo spawnPositionInfo) {
if (Barge.GetBargePopulation(true) >= ins._config.spawnConfig.maxBargeCount) return;
string bargePresetName = GetRandomBargePreset();
if (bargePresetName == null) return;
Barge.SpawnBarge(spawnPositionInfo.position, spawnPositionInfo.rotation, bargePresetName, true);
}
static string GetRandomBargePreset() {
float sumChance = 0;
foreach (var pair in ins._config.spawnConfig.probabilities) sumChance += pair.Value;
float random = UnityEngine.Random.Range(0, sumChance);
foreach (var pair in ins._config.spawnConfig.probabilities) {
random -= pair.Value;
if (random <= 0) return pair.Key;
}
return null;
}
static bool IsPositionSuitable(Vector3 position) {
if (Barge.barges.Any(x => x != null && Vector3.Distance(x.transform.position, position) < 40f)) return false;
HashSet<BaseEntity> entitiesForKill = new HashSet<BaseEntity>();
foreach (Collider collider in UnityEngine.Physics.OverlapSphere(position, 20f)) {
if (collider == null) continue;
BaseEntity entity = collider.ToBaseEntity();
if (entity == null) continue;
if (entity is BaseBoat or BaseSubmarine or CargoShip or BasePlayer) return false;
else if (entity is JunkPile or DiveSite) entitiesForKill.Add(entity);
}
foreach (BaseEntity entity in entitiesForKill) if (entity.IsExists()) entity.Kill();
return true;
}
internal static void StopSpawning() {
if (spawnLocations != null) {
spawnLocations.Clear();
spawnLocations = null;
}
if (spawnCorountine != null) ServerMgr.Instance.StopCoroutine(spawnCorountine);
spawnCorountine = null;
}
}
class SpawnPositionInfo {
internal Vector3 position;
internal Quaternion rotation;
internal SpawnPositionInfo(Vector3 position, Quaternion rotation) {
this.position = position;
this.rotation = rotation;
}
}
class FishingVilageZoneController : FacepunchBehaviour {
static HashSet<FishingVilageZoneController> zoneControllers = new HashSet<FishingVilageZoneController>();
SphereCollider sphereCollider;
const float zoneRadius = 55;
internal static void CacheVilages() {
if (!ins._config.mainConfig.blockFishingVillage) return;
foreach (MonumentInfo monumentInfo in TerrainMeta.Path.Monuments) {
if (monumentInfo.name.Contains("fishing")) {
GameObject gameObject = new GameObject("FishingVilageZoneController");
gameObject.layer = (int)Rust.Layer.Reserved1;
gameObject.transform.position = monumentInfo.transform.position;
FishingVilageZoneController zoneController = gameObject.AddComponent<FishingVilageZoneController>();
FishingVilageZoneController.zoneControllers.Add(zoneController);
}
}
}
void Awake() {
sphereCollider = gameObject.AddComponent<SphereCollider>();
sphereCollider.isTrigger = true;
sphereCollider.radius = zoneRadius;
}
void OnTriggerEnter(Collider other) {
if (other == null) return;
BaseEntity entity = other.ToBaseEntity();
if (entity == null || entity.net == null || entity.ShortPrefabName != "kayak") return;
Barge barge = Barge.GetBargeByPhysicsEntityNetId(entity.net.ID.Value);
if (barge == null) return;
BargePhysics bargePhysics = barge.GetBargePhysics();
bargePhysics.OnBargeEnterToBlockZoneZone(transform.position);
}
internal static void ClearZones() {
foreach (FishingVilageZoneController zoneController in zoneControllers) if (zoneController != null) zoneController.DeleteZone();
}
void DeleteZone() {
Destroy(this.gameObject);
}
}
class BuildingVisibilityManager : FacepunchBehaviour {
static HashSet<BuildingVisibilityManager> buildingVisibilityUpdaters = new HashSet<BuildingVisibilityManager>();
static HashSet<BuildingBlockModelInfo> buildingBlockModelInfos = new HashSet<BuildingBlockModelInfo> {
new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/wall/wall.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
9, 17, 25
}
, goodModelState = 1
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
12, 20, 28, 36, 44, 60, 68, 76, 84, 92, 100, 108, 124
}
, goodModelState = 4
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
8228, 8260, 8292, 24620, 24652, 24684, 24588,
}
, goodModelState = 8196
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
32852, 32788, 32836, 98316, 98332, 98380, 98396
}
, goodModelState = 32772
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
33, 65, 97
}
, goodModelState = 1
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
18, 66, 82
}
, goodModelState = 2
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof/roof.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
67
}
, goodModelState = 3
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof.triangle/roof.triangle.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
3, 5, 7, 9, 11, 13, 15
}
, goodModelState = 1
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/roof.triangle/roof.triangle.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
25, 49, 51, 57, 59, 8392713
}
, goodModelState = 17
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/wall.half/wall.half.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
1, 2, 3
}
, goodModelState = 0
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/wall.low/wall.low.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
1, 2, 3
}
, goodModelState = 0
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/wall.window/wall.window.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
1, 2
}
, goodModelState = 0
}
, new BuildingBlockModelInfo {
prefab = "assets/prefabs/building core/wall.doorway/wall.doorway.prefab", grade = BuildingGrade.Enum.Metal, badModelStates = new HashSet<int> {
1, 2
}
, goodModelState = 0
}
}
;
BaseEntity parentEntity;
Coroutine badBuildingBlocksCorountine;
Coroutine goodBuildingBlocksCorountine;
HashSet<BuildingBlock> badBuildingBlocks = new HashSet<BuildingBlock>();
HashSet<BuildingBlock> goodBuildingBlocks = new HashSet<BuildingBlock>();
int updatesPerTick;
internal HashSet<IoEntitySaveData> ioEntitySaveDatas = new HashSet<IoEntitySaveData>();
internal static void UpdateBuildingBlockVisibility(BuildingBlock buildingBlock) {
if (buildingBlock.net.group.subscribers.Count == 0) return;
NetWrite newWrite = Net.sv.StartWrite();
newWrite.PacketID(Message.Type.RPCMessage);
newWrite.EntityID(buildingBlock.net.ID);
newWrite.UInt32(StringPool.Get("RefreshSkin"));
newWrite.UInt64(0);
newWrite.Send(new SendInfo(buildingBlock.net.group.subscribers));
}
internal static BuildingVisibilityManager AttachVisibilityUpdater(BaseEntity parentEntity) {
GameObject triggerGameObject = new GameObject("BuildingVisibilityUpdater");
triggerGameObject.transform.SetParent(parentEntity.transform, false);
BuildingVisibilityManager buildingVisibilityUpdater = triggerGameObject.AddComponent<BuildingVisibilityManager>();
buildingVisibilityUpdater.Init(parentEntity);
buildingVisibilityUpdaters.Add(buildingVisibilityUpdater);
return buildingVisibilityUpdater;
}
internal void UpdateBuildingBlockModels() {
foreach (BaseEntity entity in parentEntity.children) {
BuildingBlock buildingBlock = entity as BuildingBlock;
if (buildingBlock != null) {
UpdateBuildingBlockModel(buildingBlock);
}
}
}
static void DefineUpdateFrequency() {
buildingVisibilityUpdaters.RemoveWhere(x => x == null);
int sumBadBuildinbBlocksCount = 0;
foreach (BuildingVisibilityManager buildingVisibilityUpdater in buildingVisibilityUpdaters) if (buildingVisibilityUpdater != null) sumBadBuildinbBlocksCount += buildingVisibilityUpdater.badBuildingBlocks.Count;
foreach (BuildingVisibilityManager buildingVisibilityUpdater in buildingVisibilityUpdaters) {
if (buildingVisibilityUpdater == null) continue;
buildingVisibilityUpdater.updatesPerTick = sumBadBuildinbBlocksCount == 0 ? 0 : buildingVisibilityUpdater.badBuildingBlocks.Count * ins._config.performanceConfig.updatePerTick / sumBadBuildinbBlocksCount;
if (buildingVisibilityUpdater.updatesPerTick > buildingVisibilityUpdater.badBuildingBlocks.Count) buildingVisibilityUpdater.updatesPerTick = buildingVisibilityUpdater.badBuildingBlocks.Count;
}
}
void Init(BaseEntity parentEntity) {
this.parentEntity = parentEntity;
}
internal void OnStartMoving() {
badBuildingBlocks.Clear();
goodBuildingBlocks.Clear();
ioEntitySaveDatas.Clear();
foreach (BaseEntity entity in parentEntity.children) {
BuildingBlock buildingBlock = entity as BuildingBlock;
if (buildingBlock != null) {
CacheBuildingBlock(buildingBlock);
continue;
}
IOEntity iOEntity = entity as IOEntity;
if (iOEntity != null) {
CacheIOEntity(iOEntity);
continue;
}
if (entity is DoorCloser) {
foreach (BaseEntity subChildren in entity.children) {
BuildingBlock subBuildingBlock = subChildren as BuildingBlock;
if (subBuildingBlock != null) CacheBuildingBlock(subBuildingBlock);
}
}
}
StopCorountines();
badBuildingBlocksCorountine = ServerMgr.Instance.StartCoroutine(BadBuildingBlocksCorountine());
goodBuildingBlocksCorountine = ServerMgr.Instance.StartCoroutine(GoodBuildingBlocksCorountine());
DefineUpdateFrequency();
}
void CacheBuildingBlock(BuildingBlock buildingBlock) {
UpdateBuildingBlockModel(buildingBlock);
if (IsBuildingBlockGoodMoving(buildingBlock)) goodBuildingBlocks.Add(buildingBlock);
else badBuildingBlocks.Add(buildingBlock);
}
void UpdateBuildingBlockModel(BuildingBlock buildingBlock) {
BuildingBlockModelInfo buildingBlockModelInfo = buildingBlockModelInfos.FirstOrDefault(x => x.prefab == buildingBlock.PrefabName && x.badModelStates.Contains(buildingBlock.modelState));
if (buildingBlockModelInfo == null) return;
buildingBlock.SetConditionalModel(buildingBlockModelInfo.goodModelState);
buildingBlock.SendNetworkUpdate();
}
bool IsBuildingBlockGoodMoving(BuildingBlock buildingBlock) {
if (buildingBlock.grade == BuildingGrade.Enum.Wood && buildingBlock.skinID == 10232) return true;
if (buildingBlock.grade == BuildingGrade.Enum.Metal && buildingBlock.skinID == 10221) {
if (buildingBlock.ShortPrefabName.Contains("floor")) return false;
else return true;
}
return false;
}
void CacheIOEntity(IOEntity iOEntity) {
HashSet<IOSlotData> inputSlotDatas = new HashSet<IOSlotData>();
HashSet<IOSlotData> outputSlotDatas = new HashSet<IOSlotData>();
foreach (var input in iOEntity.inputs) {
IOSlotData iOSlotData = GetSlotData(input);
inputSlotDatas.Add(iOSlotData);
}
foreach (var output in iOEntity.outputs) {
IOSlotData iOSlotData = GetSlotData(output);
outputSlotDatas.Add(iOSlotData);
}
iOEntity.SendNetworkUpdate();
if (inputSlotDatas.Count == 0 && outputSlotDatas.Count == 0) return;
IoEntitySaveData ioEntitySaveData = new IoEntitySaveData(iOEntity.net.ID.Value, inputSlotDatas, outputSlotDatas);
ioEntitySaveDatas.Add(ioEntitySaveData);
}
IOSlotData GetSlotData(IOEntity.IOSlot slot) {
HashSet<Vector3> linePoints = new HashSet<Vector3>();
if (slot.linePoints != null) foreach (Vector3 localPosition in slot.linePoints) linePoints.Add(localPosition);
slot.linePoints = new Vector3[1] {
Vector3.up
}
;
return new IOSlotData(linePoints);
}
IEnumerator BadBuildingBlocksCorountine() {
while (true) {
int updatesInFrame = updatesPerTick;
foreach (BuildingBlock buildingBlock in badBuildingBlocks) {
if (!buildingBlock.IsExists() || buildingBlock.IsDead()) continue;
updatesInFrame--;
UpdateBuildingBlockVisibility(buildingBlock);
if (updatesInFrame <= 0) {
updatesInFrame = updatesPerTick;
yield return CoroutineEx.waitForSeconds(0.05f);
}
}
yield return CoroutineEx.waitForSeconds(0.05f);
}
}
IEnumerator GoodBuildingBlocksCorountine() {
while (true) {
foreach (BuildingBlock buildingBlock in goodBuildingBlocks) {
if (!buildingBlock.IsExists() || buildingBlock.IsDead()) continue;
UpdateBuildingBlockVisibility(buildingBlock);
yield return CoroutineEx.waitForSeconds(0.025f);
// ... [Code preview truncated due to length. Full source in attached file] ...