C#:
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins {
[Info("NoEscape", "OxideBro", "2.4.32")]
public class NoEscape : RustPlugin {
#region Class
private static List<SphereComponent> BlockerList = new List<SphereComponent>();
private const string permMarker = "noescape.marker";
private class PlayerBlockStatus : FacepunchBehaviour {
private BasePlayer Player;
public SphereComponent CurrentBlocker;
public double CurrentTime = config.BlockSettings.BlockLength;
const string LayerPopup = "NoEscapePopupNotification";
public List<Notification> Notifications = new List<Notification>();
public class Notification {
public string Id;
public string Title;
public string Description;
public string Icon = "assets/icons/broadcast.png";
public int duration = config.uIPopupNotifications.PopupDestroyTime;
public Notification() {
Id = CuiHelper.GetGuid();
}
}
public static PlayerBlockStatus Get(BasePlayer player) {
return player.GetComponent<PlayerBlockStatus>() ?? player.gameObject.AddComponent<PlayerBlockStatus>();
}
private void Awake() {
Player = GetComponent<BasePlayer>();
}
private void ControllerUpdate() {
if (CurrentBlocker != null) UpdateUI();
else UnblockPlayer();
}
public void CreateUI() {
CuiHelper.DestroyUi(Player, "NoEscape");
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = config.UISettings.AnchorMin, AnchorMax = config.UISettings.AnchorMax, OffsetMax = "0 0"
}
, Image = {
Color = config.UISettings.InterfaceColorBP
}
}
, "Hud", "NoEscape");
CuiHelper.AddUi(Player, container);
if (CurrentBlocker != null) UpdateUI();
}
public void BlockPlayer(SphereComponent blocker, bool justCreated) {
if (ins.permission.UserHasPermission(Player.UserIDString, config.BlockSettings.PermissionToIgnore)) {
UnblockPlayer(true);
return;
}
if (justCreated) Player.ChatMessage(string.Format(ins.GetMessage("blockactiveAttacker", Player.UserIDString), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength)));
CurrentBlocker = blocker;
CurrentTime = CurrentBlocker.CurrentTime;
CreateUI();
InvokeRepeating(ControllerUpdate, 1f, 1f);
}
public void UpdateUI() {
CurrentTime++;
CuiHelper.DestroyUi(Player, "NoEscape_update");
CuiHelper.DestroyUi(Player, "NoEscape" + ".Info");
CuiElementContainer container = new CuiElementContainer();
// Фон полосы (ГОЛУБОЙ, всегда полная, НЕ ДВИГАЕТСЯ)
container.Add(new CuiElement {
Parent = "NoEscape", Name = "NoEscape_update", Components = {
new CuiImageComponent {
Color = "0.2 0.5 0.9 0.85"
}
, // ГОЛУБОЙ
new CuiRectTransformComponent {
AnchorMin = $"0 0", AnchorMax = $"1 1", OffsetMin = "0 0", OffsetMax = "0 0"
}
,
}
}
);
// Текст: "Блокировка рейда" - КРАСНЫЙ, "Осталось: время" - БЕЛЫЙ
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Text = {
Text = string.Format(ins.GetMessage("guitimertext", Player.UserIDString), ins.GetFormatTime(TimeSpan.FromSeconds(CurrentBlocker.TotalTime - CurrentTime))), Font = "robotocondensed-bold.ttf", Color = "1 1 1 1", // БЕЛЫЙ для остального текста
FontSize = 16, Align = TextAnchor.MiddleCenter
}
}
, "NoEscape", "NoEscape" + ".Info");
CuiHelper.AddUi(Player, container);
if (CurrentTime >= config.BlockSettings.BlockLength) UnblockPlayer();
}
public void UnblockPlayer(bool DoPerm = false) {
if (Player == null) {
Destroy(this);
return;
}
if (!DoPerm) Player.ChatMessage(ins.GetMessage("blocksuccess", Player.UserIDString));
CancelInvoke(ControllerUpdate);
CuiHelper.DestroyUi(Player, "NoEscape");
CurrentBlocker = null;
}
private void OnDestroy() {
CuiHelper.DestroyUi(Player, "NoEscape");
CuiHelper.DestroyUi(Player, LayerPopup);
}
public void Remove(string id) {
var remove = Notifications.Find(v => v.Id == id);
if (remove == null) return;
Notifications.Remove(remove);
DrawNotifications();
}
public void AddNotification(Notification notification) {
Notifications.Add(notification);
StartCoroutine(DestroyNotification(notification));
if (Notifications.Count > config.uIPopupNotifications.MaxPopupNotifications) Remove(Notifications.FirstOrDefault().Id);
DrawNotifications();
}
private IEnumerator DestroyNotification(Notification messageData) {
yield return new WaitForSeconds(messageData.duration);
if (messageData == null) yield break;
Notifications.Remove(messageData);
Remove(messageData.Id);
DrawNotifications();
}
public void DrawNotifications() {
CuiHelper.DestroyUi(Player, LayerPopup);
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = $"{config.uIPopupNotifications.AnchorPosX } {config.uIPopupNotifications.AnchorPosY}", AnchorMax = $"{config.uIPopupNotifications.AnchorPosX } {config.uIPopupNotifications.AnchorPosY}", OffsetMax = "0 0"
}
, Image = {
Color = "0 0 0 0"
}
}
, "Overlay", LayerPopup);
float anchor = 0;
foreach (var notify in Notifications) {
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = $"{-config.uIPopupNotifications.OffsetX} {anchor - config.uIPopupNotifications.OffsetY}", OffsetMax = $"0 {anchor}"
}
, Image = {
Color = config.uIPopupNotifications.InterfaceColor, Material = ""
}
}
, LayerPopup, LayerPopup + notify.Id);
string offset = string.IsNullOrEmpty(notify.Icon) ? "5" : "50";
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"{offset} 0", OffsetMax = "0 -5"
}
, Text = {
Text = notify.Title, Align = TextAnchor.UpperLeft, Font = "robotocondensed-bold.ttf", FontSize = 14, Color = "1 1 1 0.9"
}
}
, LayerPopup + notify.Id);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = $"{offset} 0", OffsetMax = "0 -20"
}
, Text = {
Text = notify.Description, Align = TextAnchor.UpperLeft, Font = "robotocondensed-regular.ttf", FontSize = 12, Color = "1 1 1 0.8"
}
}
, LayerPopup + notify.Id);
if (!string.IsNullOrEmpty(notify.Icon)) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0.5", AnchorMax = "0 0.5", OffsetMin = "10 -15", OffsetMax = "40 15"
}
, Button = {
Color = "0.99 0.68 0.69 1.00", Sprite = notify.Icon
}
, Text = {
Text = ""
}
}
, LayerPopup + notify.Id);
}
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "-15 -15", OffsetMax = "0 0"
}
, Button = {
Color = "0.3 0 0 0.8", Command = $"noescape_popup {notify.Id}"
}
, Text = {
Text = "X", Align = TextAnchor.MiddleCenter, FontSize = 9, Font = "robotocondensed-regular.ttf", Color = "1 0.5 0.5 1"
}
}
, LayerPopup + notify.Id);
anchor -= config.uIPopupNotifications.OffsetY + config.uIPopupNotifications.OffsetSkip;
}
CuiHelper.AddUi(Player, container);
}
}
[ConsoleCommand("noescape_popup")]
void cmdNoEscapePopupClose(ConsoleSystem.Arg args) {
var player = args.Player();
var obj = PlayerBlockStatus.Get(player);
var not = obj.Notifications.Find(v => v.Id == args.Args[0]);
if (not != null) {
obj.Notifications.Remove(not);
obj.DrawNotifications();
}
}
public void AddPlayerNotification(BasePlayer player, string attacker, string grid) {
if (!config.uIPopupNotifications.EnabledPopup) return;
var message = config.uIPopupNotifications.Message.Replace("%ATTACKER%", attacker).Replace("%GRID%", grid);
PlayerBlockStatus.Get(player).AddNotification(new PlayerBlockStatus.Notification() {
Description = message, Title = config.uIPopupNotifications.Title
}
);
}
public bool IsTeamate(ulong playerId, ulong targetId) {
RelationshipManager.PlayerTeam team1;
if (!RelationshipManager.ServerInstance.playerToTeam.TryGetValue(playerId, out team1)) {
return false;
}
RelationshipManager.PlayerTeam team2;
if (!RelationshipManager.ServerInstance.playerToTeam.TryGetValue(targetId, out team2)) {
return false;
}
return team1.teamID == team2.teamID;
}
public class SphereComponent : FacepunchBehaviour {
SphereCollider sphereCollider;
public BasePlayer initPlayer;
public List<ulong> Privilage = null;
public ulong OwnerID;
public double CurrentTime = 0;
public double TotalTime = config.BlockSettings.BlockLength;
public MapMarkerGenericRadius raidMarker;
void Awake() {
var reply = 0;
if (reply == 0) {
}
gameObject.layer = (int)Layer.Reserved1;
sphereCollider = gameObject.AddComponent<SphereCollider>();
sphereCollider.isTrigger = true;
sphereCollider.radius = config.BlockSettings.BlockerDistance;
// МАРКЕР НА КАРТЕ ОТКЛЮЧЕН
// if (config.MarkerSettings.EnableMarker)
// CreateMarker();
}
private void CreateMarker() {
raidMarker = GameManager.server.CreateEntity("assets/prefabs/tools/map/genericradiusmarker.prefab", transform.position) as MapMarkerGenericRadius;
if (raidMarker == null) return;
raidMarker.alpha = config.MarkerSettings.MarkerAlpha;
raidMarker.radius = config.MarkerSettings.MarkerRadius;
raidMarker.color1 = ins.ParseColor(config.MarkerSettings.MarkerColor1);
raidMarker.color2 = ins.ParseColor(config.MarkerSettings.MarkerColor2);
raidMarker.Spawn();
raidMarker.SendUpdate();
}
public void Init(BasePlayer player, ulong owner, List<ulong> privilage) {
initPlayer = player;
OwnerID = owner;
Privilage = privilage;
}
private void OnTriggerEnter(Collider other) {
var target = other.GetComponentInParent<BasePlayer>();
if (target == null) return;
if (ins.permission.UserHasPermission(target.UserIDString, config.BlockSettings.PermissionToIgnore)) return;
if (PlayerBlockStatus.Get(target).CurrentBlocker != null && PlayerBlockStatus.Get(target).CurrentTime > CurrentTime) {
PlayerBlockStatus.Get(target).CurrentBlocker = this;
PlayerBlockStatus.Get(target).CurrentTime = CurrentTime;
return;
}
if (PlayerBlockStatus.Get(target).CurrentBlocker != null && PlayerBlockStatus.Get(target).CurrentBlocker != this && PlayerBlockStatus.Get(target).CurrentTime > CurrentTime) {
target.ChatMessage(string.Format(ins.GetMessage("enterRaidZone", target.UserIDString), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength - CurrentTime)));
PlayerBlockStatus.Get(target).CurrentBlocker = this;
PlayerBlockStatus.Get(target).CurrentTime = CurrentTime;
return;
}
if (config.BlockSettings.ShouldBlockEnter && PlayerBlockStatus.Get(target).CurrentBlocker == null) {
PlayerBlockStatus.Get(target).BlockPlayer(this, false);
target.ChatMessage(string.Format(ins.GetMessage("enterRaidZone", target.UserIDString), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength - CurrentTime)));
}
}
private void OnTriggerExit(Collider other) {
if (!config.BlockSettings.UnBlockExit) return;
var target = other.GetComponentInParent<BasePlayer>();
if (target != null && target.userID.IsSteamId() && PlayerBlockStatus.Get(target).CurrentBlocker == this) PlayerBlockStatus.Get(target).UnblockPlayer();
}
public void FixedUpdate() {
CurrentTime += Time.deltaTime;
if (CurrentTime > TotalTime) {
if (BlockerList.Contains(this)) BlockerList.Remove(this);
DestroyMarker();
Destroy(this);
}
}
private void DestroyMarker() {
if (raidMarker != null && !raidMarker.IsDestroyed) {
raidMarker.Kill();
raidMarker = null;
}
}
private void OnDestroy() {
DestroyMarker();
}
public bool IsInBlocker(BaseEntity player) => Vector3.Distance(player.transform.position, transform.position) < config.BlockSettings.BlockerDistance;
}
#endregion
#region Variables
static PluginConfig config;
protected override void LoadDefaultConfig() {
PrintWarning("Благодарим за покупку плагина на сайте RustPlugin.ru. Если вы передадите этот плагин сторонним лицам знайте - это лишает вас гарантированных обновлений!");
config = PluginConfig.DefaultConfig();
}
protected override void LoadConfig() {
base.LoadConfig();
config = Config.ReadObject<PluginConfig>();
if (config.PluginVersion < Version) UpdateConfigValues();
Config.WriteObject(config, true);
}
void Loaded() {
if (!config.PlayerBlockSettings.CanRepair) Unsubscribe(nameof(OnStructureRepair));
else Subscribe(nameof(OnStructureRepair));
if (!config.PlayerBlockSettings.CanUpgrade) Unsubscribe(nameof(CanChangeGrade));
else Subscribe(nameof(CanChangeGrade));
if (!config.PlayerBlockSettings.CanDefaultremove) Unsubscribe(nameof(OnStructureDemolish));
else Subscribe(nameof(OnStructureDemolish));
if (!config.PlayerBlockSettings.CanBuild && !config.PlayerBlockSettings.CanPlaceObjects) Unsubscribe(nameof(CanBuild));
else Subscribe(nameof(CanBuild));
permission.RegisterPermission(config.BlockSettings.PermissionToIgnore, this);
permission.RegisterPermission(config.BlockSettings.PermissionElite, this);
permission.RegisterPermission(config.VkBotMessages.VkPrivilage, this);
permission.RegisterPermission(permMarker, this);
if (config.MarkerSettings.RequirePermission) Subscribe(nameof(CanNetworkTo));
else Unsubscribe(nameof(CanNetworkTo));
LoadDefaultMessages();
}
private void UpdateConfigValues() {
PluginConfig baseConfig = PluginConfig.DefaultConfig();
if (config.PluginVersion < Version) {
PrintWarning("Config update detected! Updating config values...");
if (config.PluginVersion < new VersionNumber(2, 2, 0)) {
config.BlockSettings.WriteListDestroyEntity = new List<string>() {
"barricade.metal", "bed_deployed"
}
;
PrintWarning("Added Write List entity");
}
if (config.PluginVersion < new VersionNumber(2, 3, 1)) {
config.PlayerBlockSettings.BlackListCommands = new List<string>() {
"/bp", "/backpack", "backpack.open", "/trade"
}
;
PrintWarning("Added Black List commands");
}
if (config.PluginVersion < new VersionNumber(2, 4, 0)) {
if (config.uIPopupNotifications == null) {
config.uIPopupNotifications = new UIPopupNotifications();
}
PrintWarning("Added UI Popup Notifications");
}
PrintWarning("Config update completed!");
config.PluginVersion = Version;
}
}
protected override void SaveConfig() {
Config.WriteObject(config);
}
public class UIPopupNotifications {
[JsonProperty("Включить Popup Notifications")]
public bool EnabledPopup = true;
[JsonProperty("Цвет фона оповещения")]
public string InterfaceColor = "0.5 0.05 0.05 0.9";
[JsonProperty("Позиция по вертикали X (0.0 - 1.0)")]
public float AnchorPosX = 0.99f;
[JsonProperty("Время жизни Popup оповещения в секундах")]
public int PopupDestroyTime = 30;
[JsonProperty("Позиция по вертикали Y (0.0 - 1.0)")]
public float AnchorPosY = 0.99f;
[JsonProperty("Ширина каждой панели (Offset X)")]
public float OffsetX = 300;
[JsonProperty("Высота каждой панели (Offset Y)")]
public float OffsetY = 50;
[JsonProperty("Пропуск между панелями (Offset)")]
public float OffsetSkip = 10;
[JsonProperty("Титл оповещения")]
public string Title = "🔴 РЕЙД АТАКА";
[JsonProperty("Текст оповещения (%ATTACKER% - Имя атакующего, %GRID% - Грит координаты)")]
public string Message = "⚠️ ВНИМАНИЕ! Игрок <b>%ATTACKER%</b> атаковал ваше строение в квадрате <b>%GRID%</b>";
[JsonProperty("Максимальное количество оповещений")]
public int MaxPopupNotifications = 3;
}
public class UISettings {
[JsonProperty("Цвет полосы")]
public string InterfaceColor = "0.2 0.5 0.9 0.85";
// ГОЛУБОЙ
[JsonProperty("Цвет фона")]
public string InterfaceColorBP = "0.3 0 0 0.7";
[JsonProperty("Позиция AnchorMin")]
public string AnchorMin = "0.3447913 0.112037";
[JsonProperty("Позиция AnchorMax")]
public string AnchorMax = "0.640625 0.1398148";
}
public class BlockSettings {
[JsonProperty("Радиус зоны блокировки")]
public float BlockerDistance = 150;
[JsonProperty("Общее время блокировки в секундах")]
public float BlockLength = 150;
[JsonProperty("Не блокировать игрока если он создатель объекта")]
public bool EnabledOwner = false;
[JsonProperty("Не блокировать игрока если он тимейт создателя объекта")]
public bool EnabledTeam = false;
[JsonProperty("Блокировать всю тиму инициатора рейда")]
public bool EnabledBlockAllTeamate = false;
[JsonProperty("Блокировать создателя объекта какой разрушили, даже если он вне зоны рейда")]
public bool BlockOwnersIfNotInZone = true;
[JsonProperty("Блокировать игрока, который вошёл в активную зону блокировки")]
public bool ShouldBlockEnter = true;
[JsonProperty("Снимать блокировку с игрока если он вышел из зоны блокировки?")]
public bool UnBlockExit = false;
[JsonProperty("Не создавать блокировку если разрушенный объект не в зоне шкафа (Нету билды)")]
public bool EnabledBuildingBlock = false;
[JsonProperty("Блокировать всех игроков какие авторизаваны в шкафу (Если шкаф существует, и авторизованный игрок на сервере)")]
public bool EnabledBlockAutCupboard = false;
[JsonProperty("Привилегия, игроки с которой игнорируются РБ (на них он не действует")]
public string PermissionToIgnore = "noescape.ignore";
[JsonProperty("Привилегия Elite (может использовать backpack во время рейда)")]
public string PermissionElite = "noescape.elite";
[JsonProperty("Белый список entity при разрушении каких не действует блокировка")]
public List<string> WriteListDestroyEntity = new List<string>();
}
public class VkBotMessages {
[JsonProperty("Включить отправку сообщения в ВК оффлайн игроку через VkBot")]
public bool EnabledVkBOT = false;
[JsonProperty("Сообщение какое будет отправлено игроку ({0} - Имя атакуещего, {1} - Квадрат на карте)")]
public string Messages = "🔴 Внимание! Игрок {0} начал рейд вашего строения в квадрате {1} на сервере SERVERNAME.";
[JsonProperty("Привилегия на использование оффлайн уведомления")]
public string VkPrivilage = "noescape.vknotification";
}
public class MarkerSettings {
[JsonProperty("Включить маркер рейда на карте")]
public bool EnableMarker = false;
// ОТКЛЮЧЕНО
[JsonProperty("Прозрачность маркера (0.0 - 1.0)")]
public float MarkerAlpha = 0.8f;
[JsonProperty("Радиус маркера на карте")]
public float MarkerRadius = 0.5f;
[JsonProperty("Основной цвет маркера (HEX)")]
public string MarkerColor1 = "#FF0000";
[JsonProperty("Второй цвет маркера (HEX)")]
public string MarkerColor2 = "#8B0000";
[JsonProperty("Показывать маркер только игрокам с правом noescape.marker")]
public bool RequirePermission = false;
}
public class PlayerBlockSettings {
[JsonProperty("Блокировать использование китов")]
public bool CanUseKits = true;
[JsonProperty("Блокировать обмен между игроками (Trade)")]
public bool CanUseTrade = true;
[JsonProperty("Блокировать телепорты")]
public bool CanTeleport = true;
[JsonProperty("Блокировать удаление построек (CanRemove)")]
public bool CanRemove = true;
[JsonProperty("Блокировать улучшение построек (Upgrade, BuildingUpgrade и прочее)")]
public bool CanBGrade = true;
[JsonProperty("Блокировать удаление построек (стандартное)")]
public bool CanDefaultremove = true;
[JsonProperty("Блокировать строительство")]
public bool CanBuild = true;
[JsonProperty("Блокировать установку объектов")]
public bool CanPlaceObjects = true;
[JsonProperty("Блокировать ремонт построек (стандартный)")]
public bool CanRepair = true;
[JsonProperty("Блокировать улучшение построек (стандартное)")]
public bool CanUpgrade = true;
[JsonProperty("Белый список предметов какие можно строить при блокировке")]
public List<string> WriteListBuildEntity = new List<string>() {
"wall.external.high.stone", "barricade.metal", "barricade.wood.cover", "ladder.wooden.wall", "sleepingbag", // РАЗРЕШАЕМ СОЛОМЕННУЮ СТЕНУ
"wall", "wall.low", "wall.frame", "wall.half", "wall.doorway", "floor", "floor.frame", "stairs", "stairs.lshape", "stairs.spiral", "roof", "window.frame", "pillar", "foundation", "foundation.triangular", "twig"
}
;
[JsonProperty("Черный список команд какие запрещены при рейд блоке (Чатовые и консольные)")]
public List<string> BlackListCommands = new List<string>();
}
private class PluginConfig {
[JsonProperty("Настройка UI")]
public UISettings UISettings = new UISettings();
[JsonProperty("Настройка Popup Notifications")]
public UIPopupNotifications uIPopupNotifications = new UIPopupNotifications();
[JsonProperty("Общая настройка блокировки")]
public BlockSettings BlockSettings = new BlockSettings();
[JsonProperty("Настройка запретов для игрока")]
public PlayerBlockSettings PlayerBlockSettings = new PlayerBlockSettings();
[JsonProperty("Настройка VkBOT")]
public VkBotMessages VkBotMessages = new VkBotMessages();
[JsonProperty("Настройка маркера рейда на карте")]
public MarkerSettings MarkerSettings = new MarkerSettings();
[JsonProperty("Версия конфигурации")]
public VersionNumber PluginVersion = new VersionNumber();
[JsonIgnore]
[JsonProperty("Инициализация плагина")]
public bool Init = false;
public static PluginConfig DefaultConfig() {
return new PluginConfig {
uIPopupNotifications = new UIPopupNotifications() {
EnabledPopup = true, InterfaceColor = "0.5 0.05 0.05 0.9", Title = "🔴 РЕЙД АТАКА", Message = "⚠️ ВНИМАНИЕ! Игрок <b>%ATTACKER%</b> атаковал ваше строение в квадрате <b>%GRID%</b>", AnchorPosX = 0.99f, AnchorPosY = 0.99f, OffsetX = 300, OffsetY = 50, OffsetSkip = 10, PopupDestroyTime = 30, MaxPopupNotifications = 3
}
, BlockSettings = new BlockSettings() {
BlockerDistance = 150, BlockLength = 150, BlockOwnersIfNotInZone = true, ShouldBlockEnter = true, UnBlockExit = false, EnabledBuildingBlock = false, EnabledBlockAutCupboard = false, PermissionToIgnore = "noescape.ignore", PermissionElite = "noescape.elite", WriteListDestroyEntity = new List<string>() {
"barricade.metal", "bed_deployed"
}
}
, PlayerBlockSettings = new PlayerBlockSettings() {
CanUseKits = true, CanUseTrade = true, CanTeleport = true, CanRemove = true, CanBGrade = true, CanDefaultremove = true, CanBuild = true, CanPlaceObjects = true, CanRepair = true, CanUpgrade = true, WriteListBuildEntity = new List<string>() {
"wall.external.high.stone", "barricade.metal", "barricade.wood.cover", "ladder.wooden.wall", "sleepingbag", // РАЗРЕШАЕМ СОЛОМЕННУЮ СТЕНУ
"wall", "wall.low", "wall.frame", "wall.half", "wall.doorway", "floor", "floor.frame", "stairs", "stairs.lshape", "stairs.spiral", "roof", "window.frame", "pillar", "foundation", "foundation.triangular", "twig"
}
, BlackListCommands = new List<string>() {
"/bp", "/backpack", "backpack.open", "/trade"
}
}
, UISettings = new UISettings() {
InterfaceColor = "0.2 0.5 0.9 0.85", // ГОЛУБОЙ
InterfaceColorBP = "0.3 0 0 0.7", AnchorMin = "0.3447913 0.112037", AnchorMax = "0.640625 0.1398148",
}
, VkBotMessages = new VkBotMessages() {
EnabledVkBOT = false, Messages = "🔴 Внимание! Игрок {0} начал рейд вашего строения в квадрате {1} на сервере SERVERNAME.", VkPrivilage = "noescape.vknotification",
}
, MarkerSettings = new MarkerSettings() {
EnableMarker = false, // ОТКЛЮЧЕНО
MarkerAlpha = 0.8f, MarkerRadius = 0.5f, MarkerColor1 = "#FF0000", MarkerColor2 = "#8B0000", RequirePermission = false,
}
, PluginVersion = new VersionNumber(),
}
;
}
}
#endregion
#region Oxide
private static NoEscape ins;
private void OnServerInitialized() {
ins = this;
config.Init = true;
BasePlayer.activePlayerList.ToList().ForEach(OnPlayerConnected);
}
void OnPlayerSleepEnded(BasePlayer player) {
SphereComponent ActiveRaidZone = GetRaidZone(player.transform.position);
if (ActiveRaidZone == null) {
if (config.BlockSettings.UnBlockExit) {
if (PlayerBlockStatus.Get(player).CurrentBlocker != null) PlayerBlockStatus.Get(player).UnblockPlayer();
}
return;
}
if (PlayerBlockStatus.Get(player).CurrentBlocker != null) {
if (PlayerBlockStatus.Get(player).CurrentBlocker != ActiveRaidZone) PlayerBlockStatus.Get(player).BlockPlayer(ActiveRaidZone, false);
}
else {
player.ChatMessage(string.Format(GetMessage("enterRaidZone", player.UserIDString), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength - ActiveRaidZone.CurrentTime)));
PlayerBlockStatus.Get(player)?.BlockPlayer(ActiveRaidZone, false);
}
}
private void OnPlayerConnected(BasePlayer player) {
if (player.IsReceivingSnapshot) {
timer.In(1f, () => OnPlayerConnected(player));
return;
}
if (PlayerBlockStatus.Get(player).CurrentBlocker != null) PlayerBlockStatus.Get(player).CreateUI();
}
private void Unload() {
foreach (var player in BasePlayer.activePlayerList) if (PlayerBlockStatus.Get(player) != null) UnityEngine.Object.Destroy(PlayerBlockStatus.Get(player));
BlockerList.RemoveAll(x => {
if (x.raidMarker != null && !x.raidMarker.IsDestroyed) x.raidMarker.Kill();
UnityEngine.Object.Destroy(x);
return true;
}
);
}
private object CanNetworkTo(MapMarkerGenericRadius marker, BasePlayer player) {
if (marker == null || player == null) return null;
foreach (var blocker in BlockerList) {
if (blocker.raidMarker == marker) {
if (!permission.UserHasPermission(player.UserIDString, permMarker)) return false;
break;
}
}
return null;
}
private Color ParseColor(string hexColor) {
if (string.IsNullOrEmpty(hexColor)) return Color.red;
if (!hexColor.StartsWith("#")) hexColor = "#" + hexColor;
Color color;
if (ColorUtility.TryParseHtmlString(hexColor, out color)) return color;
return Color.red;
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (!config.Init) return;
if (entity == null || info == null || info.InitiatorPlayer == null || !(entity is StabilityEntity || entity is ShopFront || entity is BuildingPrivlidge) || config.BlockSettings.EnabledBuildingBlock && entity.GetBuildingPrivilege() == null || entity.OwnerID == 0 || (config.BlockSettings.EnabledOwner && info.InitiatorPlayer.userID == entity.OwnerID) || (config.BlockSettings.EnabledTeam && IsTeamate(info.InitiatorPlayer.userID, entity.OwnerID))) return;
if (entity is BuildingBlock && (entity as BuildingBlock).currentGrade.gradeBase.type == BuildingGrade.Enum.Twigs || info?.damageTypes.GetMajorityDamageType() == DamageType.Decay || config.BlockSettings.WriteListDestroyEntity.Contains(entity.ShortPrefabName)) return;
var alreadyBlock = BlockerList.FirstOrDefault(p => Vector3.Distance(entity.transform.position, p.transform.position) < (config.BlockSettings.BlockerDistance / 2));
if (alreadyBlock) {
alreadyBlock.CurrentTime = 0;
if (config.BlockSettings.BlockOwnersIfNotInZone) {
var OwnerPlayer = BasePlayer.FindByID(entity.OwnerID);
if (OwnerPlayer != null) PlayerBlockStatus.Get(OwnerPlayer).BlockPlayer(alreadyBlock, false);
}
PlayerBlockStatus.Get(info.InitiatorPlayer).BlockPlayer(alreadyBlock, false);
if (config.BlockSettings.EnabledBlockAllTeamate && info.InitiatorPlayer.currentTeam != 0) {
var team = RelationshipManager.ServerInstance.FindTeam(info.InitiatorPlayer.currentTeam);
foreach (var userID in team.members) {
BasePlayer basePlayer = global : : BasePlayer.FindByID(userID);
if (basePlayer != null && basePlayer.IsConnected) PlayerBlockStatus.Get(basePlayer).BlockPlayer(alreadyBlock, false);
}
}
if (entity.GetBuildingPrivilege() != null) {
foreach (var aplayer in entity.GetBuildingPrivilege().authorizedPlayers) {
var AuthPlayer = BasePlayer.Find(aplayer.ToString());
if (config.BlockSettings.EnabledBlockAutCupboard && AuthPlayer != null && AuthPlayer != info.InitiatorPlayer && AuthPlayer.IsConnected) PlayerBlockStatus.Get(AuthPlayer).BlockPlayer(alreadyBlock, false);
else if (AuthPlayer == null || !AuthPlayer.IsConnected) SendOfflineMEssages(entity.transform.position, info.InitiatorPlayer.displayName, aplayer.userid);
}
}
var col = Vis.colBuffer;
var count = Physics.OverlapSphereNonAlloc(alreadyBlock.transform.position, config.BlockSettings.BlockerDistance, col, LayerMask.GetMask("Player (Server)"));
for (int i = 0; i < count; i++) {
var player = col[i].ToBaseEntity() as BasePlayer;
if (player == null) continue;
PlayerBlockStatus.Get(player).BlockPlayer(alreadyBlock, false);
}
}
else {
var obj = new GameObject();
obj.transform.position = entity.transform.position;
var sphere = obj.AddComponent<SphereComponent>();
sphere.GetComponent<SphereComponent>().Init(info.InitiatorPlayer, entity.OwnerID, entity.GetBuildingPrivilege() != null ? entity.GetBuildingPrivilege().authorizedPlayers.Select(p => p.userid).ToList() : null);
BlockerList.Add(sphere);
PlayerBlockStatus.Get(info.InitiatorPlayer).BlockPlayer(sphere, true);
if (config.BlockSettings.EnabledBlockAllTeamate && info.InitiatorPlayer.currentTeam != 0) {
var team = RelationshipManager.ServerInstance.FindTeam(info.InitiatorPlayer.currentTeam);
foreach (var userID in team.members) {
BasePlayer basePlayer = global : : BasePlayer.FindByID(userID);
if (basePlayer != null && basePlayer.IsConnected) PlayerBlockStatus.Get(basePlayer).BlockPlayer(sphere, false);
}
}
var OwnerPlayer = BasePlayer.FindByID(entity.OwnerID);
if (OwnerPlayer == null || !OwnerPlayer.IsConnected) {
SendOfflineMEssages(entity.transform.position, info.InitiatorPlayer.displayName, entity.OwnerID);
}
else if (OwnerPlayer != null) {
if (config.BlockSettings.BlockOwnersIfNotInZone) PlayerBlockStatus.Get(OwnerPlayer)?.BlockPlayer(sphere, false);
OwnerPlayer.ChatMessage(string.Format(GetMessage("blockactive", OwnerPlayer.UserIDString), GetGridString(entity.transform.position), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength)));
AddPlayerNotification(OwnerPlayer, info.InitiatorPlayer.displayName, GetGridString(entity.transform.position));
}
var col = Vis.colBuffer;
var count = Physics.OverlapSphereNonAlloc(sphere.transform.position, config.BlockSettings.BlockerDistance, col, LayerMask.GetMask("Player (Server)"));
for (int i = 0; i < count; i++) {
var player = col[i].ToBaseEntity() as BasePlayer;
if (player == null || !player.IsConnected || OwnerPlayer == player) continue;
PlayerBlockStatus.Get(player).BlockPlayer(sphere, false);
}
if (entity.GetBuildingPrivilege() != null) {
foreach (var aplayer in entity.GetBuildingPrivilege().authorizedPlayers) {
var AuthPlayer = BasePlayer.Find(aplayer.ToString());
if (AuthPlayer != null && AuthPlayer != info.InitiatorPlayer && OwnerPlayer != AuthPlayer) {
if (config.BlockSettings.EnabledBlockAutCupboard) PlayerBlockStatus.Get(AuthPlayer).BlockPlayer(sphere, false);
AddPlayerNotification(AuthPlayer, info.InitiatorPlayer.displayName, GetGridString(entity.transform.position));
SendReply(AuthPlayer, string.Format(GetMessage("blockactiveAuthCup", AuthPlayer.UserIDString), GetGridString(entity.transform.position), NumericalFormatter.FormatTime(config.BlockSettings.BlockLength)));
}
else if (AuthPlayer != info.InitiatorPlayer && OwnerPlayer != AuthPlayer) SendOfflineMEssages(entity.transform.position, info.InitiatorPlayer.displayName, aplayer.userid);
}
}
}
}
object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
var player = planner.GetOwnerPlayer();
if (player == null || !IsRaidBlocked(player)) return null;
if (permission.UserHasPermission(player.UserIDString, config.BlockSettings.PermissionElite)) return null;
var shortname = prefab.hierachyName.Substring(prefab.hierachyName.IndexOf("/") + 1);
var fullName = prefab.fullName ?? "";
var prefabName = prefab.prefabID.ToString();
foreach (var allowed in config.PlayerBlockSettings.WriteListBuildEntity) {
if (shortname.Contains(allowed) || fullName.Contains(allowed) || allowed.Contains(shortname)) return null;
}
var component = PlayerBlockStatus.Get(player);
if (component == null || component.CurrentBlocker == null) return null;
player.ChatMessage(string.Format(GetMessage("blockbuld", player.UserIDString), NumericalFormatter.FormatTime(component.CurrentBlocker.TotalTime - component.CurrentTime)));
return false;
}
private object OnUserCommand(IPlayer ipl, string command, string[] args) {
if (ipl == null || !ipl.IsConnected) return null;
var player = ipl.Object as BasePlayer;
command = command.Insert(0, "/");
if (player == null || !IsRaidBlocked(player)) return null;
if (config.PlayerBlockSettings.BlackListCommands.Contains(command.ToLower())) {
string cmdLower = command.ToLower();
if ((cmdLower == "/backpack" || cmdLower == "/bp" || cmdLower.Contains("backpack")) && permission.UserHasPermission(player.UserIDString, config.BlockSettings.PermissionElite)) return null;
var component = PlayerBlockStatus.Get(player);
if (component == null || component.CurrentBlocker == null) return null;
player.ChatMessage(string.Format(GetMessage("commandBlock", player.UserIDString), NumericalFormatter.FormatTime(component.CurrentBlocker.TotalTime - component.CurrentTime)));
return false;
}
return null;
}
private object OnServerCommand(ConsoleSystem.Arg arg) {
var connection = arg.Connection;
if (connection == null || string.IsNullOrEmpty(arg.cmd?.FullName)) return null;
var player = arg.Player();
if (player == null || !IsRaidBlocked(player)) return null;
if (config.PlayerBlockSettings.BlackListCommands.Contains(arg.cmd.Name.ToLower()) || config.PlayerBlockSettings.BlackListCommands.Contains(arg.cmd.FullName.ToLower())) {
string cmdName = arg.cmd.Name.ToLower();
string cmdFull = arg.cmd.FullName.ToLower();
if ((cmdName.Contains("backpack") || cmdFull.Contains("backpack") || cmdName == "bp") && permission.UserHasPermission(player.UserIDString, config.BlockSettings.PermissionElite)) return null;
var component = PlayerBlockStatus.Get(player);
if (component == null || component.CurrentBlocker == null) return null;
player.ChatMessage(string.Format(GetMessage("commandBlock", player.UserIDString), NumericalFormatter.FormatTime(component.CurrentBlocker.TotalTime - component.CurrentTime)));
return false;
}
return null;
}
#endregion
#region Functions
private string GetGridString(Vector3 pos) {
char letter = 'A';
var x = Mathf.Floor((pos.x + (ConVar.Server.worldsize / 2)) / 146.3f) % 26;
var z = (Mathf.Floor(ConVar.Server.worldsize / 146.3f) - 1) - Mathf.Floor((pos.z + (ConVar.Server.worldsize / 2)) / 146.3f);
letter = (char)(((int)letter) + x);
return $"{letter}{z}";
}
private string NumberToString(int number) {
bool a = number > 26;
Char c = (Char)(65 + (a ? number - 26 : number));
return a ? "A" + c : c.ToString();
}
[PluginReference]
private Plugin VKBot;
private static void SendOfflineMEssages(Vector3 pos, string name = "", ulong playerid = 0) {
if (!ins.permission.UserHasPermission(playerid.ToString(), config.VkBotMessages.VkPrivilage)) return;
string receiver = (string)ins.VKBot?.Call("GetUserVKId", playerid) ?? "";
if (string.IsNullOrEmpty(receiver)) return;
ins.VKBot?.Call("SendVkMessage", receiver, config.VkBotMessages.Messages.Replace("{0}", name).Replace("{1}", ins.GetGridString(pos)));
}
private string GetFormatTime(TimeSpan timespan) {
return string.Format(timespan.TotalHours >= 1 ? "{2:00}:{0:00}:{1:00}" : "{0:00}:{1:00}", timespan.Minutes, timespan.Seconds, System.Math.Floor(timespan.TotalHours));
}
private string GetMessage(string key, string playerId) {
return lang.GetMessage(key, this, playerId);
}
private static class NumericalFormatter {
private static string GetNumEndings(int origNum, string[] forms) {
string result;
var num = origNum % 100;
if (num >= 11 && num <= 19) {
result = forms[2];
}
else {
num = num % 10;
switch (num) {
case 1 : result = forms[0];
break;
case 2 : case 3 : case 4 : result = forms[1];
break;
default : result = forms[2];
break;
}
}
return string.Format("{0} {1} ", origNum, result);
}
private static string FormatSeconds(int seconds) => GetNumEndings(seconds, new[] {
"секунду", "секунды", "секунд"
}
);
private static string FormatMinutes(int minutes) => GetNumEndings(minutes, new[] {
"минуту", "минуты", "минут"
}
);
private static string FormatHours(int hours) => GetNumEndings(hours, new[] {
"час", "часа", "часов"
}
);
private static string FormatDays(int days) => GetNumEndings(days, new[] {
"день", "дня", "дней"
}
);
private static string FormatTime(TimeSpan timeSpan) {
string result = string.Empty;
if (timeSpan.Days > 0) result += FormatDays(timeSpan.Days);
if (timeSpan.Hours > 0) result += FormatHours(timeSpan.Hours);
if (timeSpan.Minutes > 0) result += FormatMinutes(timeSpan.Minutes);
// ... [Code preview truncated due to length. Full source in attached file] ...