C#:
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
namespace Oxide.Plugins {
[Info("PlayersProtected", "https://topplugin.ru/", "1.3.0")]
class PlayersProtected : RustPlugin {
static PlayersProtected ins;
[PluginReference]
Plugin ImageLibrary;
public bool AddImage(string url, string shortname, ulong playerid = 3338240) => (bool)ImageLibrary?.Call("AddImage", url, shortname, playerid);
public string GetImages(string shortname, ulong skin = 0) => (string)ImageLibrary?.Call("GetImage", shortname, skin);
public bool IsReady() => (bool)ImageLibrary?.Call("IsReady");
private 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);
}
protected override void SaveConfig() {
Config.WriteObject(config);
}
private class PluginConfig {
[JsonProperty("Включить отображение UI защиты у игрока | Enabled UI")]
public bool UIEnabled = true;
[JsonProperty("Привилегия на использование защиты | Protected permission ")]
public string Permission = "PlayersProtected.use";
[JsonProperty("Отключить защиту на постройки игрока (Если он сам атакующий) | Disable player building protection (If he is the initiator)")]
public bool OwnerEnabled = true;
[JsonProperty("Задержка отправки сообщений об защите в чат (в секундах) | Delay in sending chat protection messages in seconds")]
public int CooldownTimer = 15;
[JsonProperty("Время защиты новых игроков или же после вайпа (в секундах) | Time to protect new players or after wipe (in seconds)")]
public double TimeToProtection = 7200.0;
[JsonProperty("Включить защиту построек у игрока | Enable player building protection")]
public bool EnabledProtectionBuild = true;
[JsonProperty("Включить защиту игрока | Enable player protection")]
public bool EnabledProtectionPlayer = true;
[JsonProperty("Включить автоматический вайп данных при вайпе карты | Enable automatic data wipe with wipe map")]
public bool AutoWipe = true;
[JsonProperty("Ссылка на изображение UI | Image URL")]
public string ImageURL = "https://i.imgur.com/b7PMaQ5.png";
[JsonProperty("Отключить защиту игрока если он в чужой билде | Disable player protection if he is in someone else's build")]
public bool DisableBuildingBlock = true;
[JsonProperty("Включить UI отображение игрока в чужой билде (если включено общее UI)| Enable UI display of the player in a foreign build (if the general UI is enabled)")]
public bool EnabledBlockUI = true;
[JsonProperty("Версия конфигурации | Configuration version")]
public VersionNumber PluginVersion = new VersionNumber();
public static PluginConfig DefaultConfig() {
return new PluginConfig() {
CooldownTimer = 15, OwnerEnabled = true, TimeToProtection = 7200, UIEnabled = true, AutoWipe = true, EnabledProtectionBuild = true, EnabledProtectionPlayer = true, ImageURL = "https://i.imgur.com/b7PMaQ5.png", PluginVersion = new VersionNumber(),
}
;
}
}
private void UpdateConfigValues() {
PrintWarning("Config update detected! Updating config values...");
PluginConfig baseConfig = PluginConfig.DefaultConfig();
if (config.PluginVersion < new VersionNumber(1, 1, 0)) config.Permission = "PlayersProtected.use";
config.PluginVersion = Version;
PrintWarning("Config update completed!");
}
class DataStorage {
public Dictionary<ulong, PlayerProtected> PlayersDatabase = new Dictionary<ulong, PlayerProtected>();
public DataStorage() {
}
}
private List<BasePlayer> Players = new List<BasePlayer>() {
}
;
DataStorage data;
public class PlayerProtected {
[JsonProperty("Время защиты")]
public double EndProtected;
}
void Loaded() {
LoadData();
lang.RegisterMessages(Messages, this, "en");
Messages = lang.GetMessages("en", this);
permission.RegisterPermission(config.Permission, this);
}
void OnServerInitialized() {
ins = this;
if (!plugins.Exists("ImageLibrary")) {
PrintError("ImageLibrary can not be found! Can not continue");
Interface.Oxide.UnloadPlugin(Title);
return;
}
AddImage(config.ImageURL, config.ImageURL, 0);
BasePlayer.activePlayerList.ToList().ForEach(OnPlayerConnected);
}
void OnUserPermissionGranted(string id, string permName) {
if (permName == config.Permission.ToLower()) {
var player = BasePlayer.FindByID(ulong.Parse(id));
if (player != null) OnPlayerConnected(player);
}
}
private bool GetConfig<T>(string MainMenu, string Key, ref T var) {
if (Config[MainMenu, Key] != null) {
var = (T)Convert.ChangeType(Config[MainMenu, Key], typeof(T));
return false;
}
Config[MainMenu, Key] = var;
return true;
}
void OnPlayerConnected(BasePlayer player) {
if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.Once(2, () => OnPlayerConnected(player));
return;
}
if (permission.UserHasPermission(player.UserIDString, config.Permission)) {
if (!data.PlayersDatabase.ContainsKey(player.userID)) data.PlayersDatabase.Add(player.userID, new PlayerProtected() {
EndProtected = GrabCurrentTime() + config.TimeToProtection
}
);
if (config.UIEnabled) {
var endtimer = data.PlayersDatabase[player.userID].EndProtected;
double time = GrabCurrentTime();
if (endtimer > time) {
var Component = player.GetComponent<PlayerMono>();
if (Component == null) player.gameObject.AddComponent<PlayerMono>();
}
}
}
}
void OnNewSave() {
PrintWarning("Обнаружен вайп, очищаем данныe об игроках");
LoadData();
data = new DataStorage();
}
void LoadData() {
try {
data = Interface.GetMod().DataFileSystem.ReadObject<DataStorage>("PlayersProtected");
if (data == null) data = new DataStorage();
}
catch {
data = new DataStorage();
}
}
void Unload() {
foreach (var player in BasePlayer.activePlayerList) {
PlayerMono component = player.GetComponent<PlayerMono>();
if (component != null) component.Disconnect();
}
BasePlayer.activePlayerList.ToList().ForEach(player => CuiHelper.DestroyUi(player, "UIPlayer"));
SaveData();
}
void SaveData() {
if (data != null) Interface.Oxide.DataFileSystem.WriteObject("PlayersProtected", data);
}
private double GrabCurrentTime() => DateTime.UtcNow.ToLocalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
private Dictionary<BasePlayer, DateTime> Cooldown = new Dictionary<BasePlayer, DateTime>();
[PluginReference]
Plugin Duel;
bool InDuel(BasePlayer player) => Duel?.Call<bool>("IsPlayerOnActiveDuel", player) ?? false;
void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null || entity?.net?.ID == null || info.Initiator == null) return;
BasePlayer attacker = info?.Initiator as BasePlayer;
if (attacker == null || IsNPC(attacker) || InDuel(attacker)) return;
double CurrentTime = GrabCurrentTime();
if (config.EnabledProtectionBuild && entity.OwnerID != 0 && entity.GetComponent<BaseEntity>() != null && entity.GetBuildingPrivilege() != null) {
if (config.OwnerEnabled) if (attacker.userID == entity.OwnerID) return;
var block = entity as BuildingBlock;
if (block != null) if (block.grade <= 0) return;
if (permission.UserHasPermission(entity.OwnerID.ToString(), config.Permission) && data.PlayersDatabase.ContainsKey(entity.OwnerID)) {
double OwnerTime = data.PlayersDatabase.ContainsKey(entity.OwnerID) ? data.PlayersDatabase[entity.OwnerID].EndProtected : 0;
if (OwnerTime > CurrentTime) {
info.damageTypes.ScaleAll(0.0f);
if (!Cooldown.ContainsKey(attacker) || Cooldown[attacker].Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds < CurrentTime) {
SendReply(attacker, Messages["OwnerProtected"]);
Cooldown[attacker] = Cooldown[attacker] = DateTime.UtcNow.ToLocalTime().AddSeconds(config.CooldownTimer);
}
}
}
}
var victim = entity.GetComponent<BasePlayer>();
if (config.EnabledProtectionPlayer && victim != null && !IsNPC(victim) && (permission.UserHasPermission(attacker.UserIDString, config.Permission) && data.PlayersDatabase.ContainsKey(attacker.userID) || permission.UserHasPermission(victim.UserIDString, config.Permission) && data.PlayersDatabase.ContainsKey(victim.userID)) /*&& victim != attacker*/
) {
if (permission.UserHasPermission(attacker.UserIDString, config.Permission) && data.PlayersDatabase.ContainsKey(attacker.userID)) {
double AttacketTime = data.PlayersDatabase[attacker.userID].EndProtected;
if (AttacketTime > CurrentTime) {
info.damageTypes.ScaleAll(0.0f);
if (!Cooldown.ContainsKey(attacker) || Cooldown[attacker].Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds < CurrentTime) {
SendReply(attacker, Messages["ProtectedOn"], FormatTime(AttacketTime - CurrentTime));
Cooldown[attacker] = DateTime.UtcNow.ToLocalTime().AddSeconds(config.CooldownTimer);
}
}
}
if (permission.UserHasPermission(victim.UserIDString, config.Permission) && data.PlayersDatabase.ContainsKey(victim.userID)) {
if (config.DisableBuildingBlock && victim.GetBuildingPrivilege() != null && !victim.IsBuildingAuthed()) return;
double VictimTime = data.PlayersDatabase[victim.userID].EndProtected;
if (VictimTime > CurrentTime) {
info.damageTypes.ScaleAll(0.0f);
if (!Cooldown.ContainsKey(attacker) || Cooldown[attacker].Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds < CurrentTime) {
SendReply(attacker, Messages["ProtectedOnPlayer"]);
Cooldown[attacker] = DateTime.UtcNow.ToLocalTime().AddSeconds(config.CooldownTimer);
}
}
}
}
}
private string FormatTime(double time) {
TimeSpan dateDifference = TimeSpan.FromSeconds(time);
var days = dateDifference.Days;
var hours = dateDifference.Hours;
var mins = dateDifference.Minutes;
var secs = dateDifference.Seconds;
if (days > 10) return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", days, hours, mins, secs);
if (days > 0) return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", days, hours, mins, secs);
if (hours > 0) return string.Format("{0:00}:{1:00}:{2:00}", hours, mins, secs);
else return string.Format("{0:00}:{1:00}", mins, secs);
}
private bool IsNPC(BasePlayer player) {
if (player == null) return false;
if (player is NPCPlayer || player.GetComponent<NPCPlayer>() != null || !player.userID.IsSteamId()) return true;
if (!(player.userID >= 76560000000000000L || player.userID <= 0L) || player.userID.ToString().Length < 17) return true;
return false;
}
[ChatCommand("protected")]
void cmdProtected(BasePlayer player, string cmd, string[] args) {
double time = GrabCurrentTime();
if (args == null || args.Length <= 0) {
var messages = data.PlayersDatabase[player.userID].EndProtected > time ? Messages["ProtectedAlready"].Replace("{0}", FormatTime(data.PlayersDatabase[player.userID].EndProtected - time)) : Messages["ProtectedAlreadyOff"];
if (player.IsAdmin) messages = $"{messages}\n\n{Messages["CmdHelpAdmin"]}";
SendReply(player, Messages["CmdHelp"], messages);
return;
}
switch (args[0]) {
case "off" : data.PlayersDatabase[player.userID].EndProtected = time;
SendReply(player, Messages["CmdProtectedOff"]);
break;
case "on" : if (!player.IsAdmin) return;
data.PlayersDatabase[player.userID].EndProtected = time + Convert.ToDouble(args[1]);
OnPlayerConnected(player);
break;
case "wipe" : if (!player.IsAdmin) return;
OnNewSave();
SendReply(player, "PlayersProtected Wiped!");
BasePlayer.activePlayerList.ToList().ForEach(OnPlayerConnected);
break;
}
}
private class PlayerMono : FacepunchBehaviour {
public BasePlayer player;
List<BasePlayer> PlayersListed = new List<BasePlayer>();
string Color = "1 1 1 0.8";
void Awake() {
player = GetComponent<BasePlayer>();
CreateUI();
InvokeRepeating(Repeater, 1f, 1f);
}
void Repeater() {
if (player == null || !player.IsConnected) {
Destroy(this);
return;
}
if (ins.data.PlayersDatabase.ContainsKey(player.userID)) {
var endtimer = ins.data.PlayersDatabase[player.userID].EndProtected;
double time = ins.GrabCurrentTime();
if (ins.config.DisableBuildingBlock && ins.config.EnabledBlockUI && player.GetBuildingPrivilege() != null) {
var color = ins.config.DisableBuildingBlock && player.IsBuildingBlocked() ? "1.00 0.00 0.00 0.8" : "1 1 1 0.8";
if (Color != color) {
if (ins.config.DisableBuildingBlock && player.IsBuildingBlocked()) {
player.ChatMessage(ins.Messages["DisabledProcOnBuildingBlock"]);
}
else {
player.ChatMessage(ins.Messages["OutInBuildingBlock"]);
}
Color = color;
CreateUI();
}
}
else if (Color != "1 1 1 0.8") {
Color = "1 1 1 0.8";
CreateUI();
player.ChatMessage(ins.Messages["OutInBuildingBlock"]);
}
if (endtimer > time) {
if (!PlayersListed.Contains(player)) PlayersListed.Add(player);
UpdateTimer(player);
}
else {
if (PlayersListed.Contains(player)) CuiHelper.DestroyUi(player, "UIPlayer");
Disconnect();
}
}
else {
Disconnect();
}
}
public void CreateUI() {
CuiHelper.DestroyUi(player, "UIPlayer");
if (!ins.IsReady()) {
ins.timer.In(1f, () => CreateUI());
return;
}
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
Image = {
Color="1 1 1 0"
}
, RectTransform = {
AnchorMin="0.006 0", AnchorMax="0.006 0", OffsetMin=$"0.1 610", OffsetMax=$"30 640"
}
,
}
, "Hud", "UIPlayer");
container.Add(new CuiElement {
Parent = "UIPlayer", Components = {
new CuiRawImageComponent {
Png=ins.GetImages(ins.config.ImageURL), Color= Color
}
, new CuiRectTransformComponent {
AnchorMin="0 0", AnchorMax="1 1"
}
,
}
,
}
);
CuiHelper.AddUi(player, container);
UpdateTimer(player);
}
public void UpdateTimer(BasePlayer player) {
CuiHelper.DestroyUi(player, "UIPlayer_timer");
CuiElementContainer Container = new CuiElementContainer();
double time = ins.GrabCurrentTime();
double currentime = ins.data.PlayersDatabase[player.userID].EndProtected;
Container.Add(new CuiElement {
Name = "UIPlayer_timer", Parent = "UIPlayer", Components = {
new CuiTextComponent {
Text= ins.FormatTime(currentime - time).ToString(), Align=TextAnchor.MiddleCenter, FontSize=11, Color= Color,
}
, new CuiRectTransformComponent {
AnchorMin="0 -0.6", AnchorMax="1 0"
}
}
,
}
);
CuiHelper.AddUi(player, Container);
}
void OnDestroy() => Disconnect();
public void Disconnect() {
if (PlayersListed.Contains(player)) PlayersListed.Remove(player);
Destroy(this);
}
}
Dictionary<string, string> Messages = new Dictionary<string, string>() {
{
"ProtectedOn", "У Вас включена защита после вайпа! Ваши постройки защищены, Вы так же не можете наносить урон по игрокам и по постройкам.Время до окончания <color=#F0AE79>{0}</color>.\nЧто бы отключить защиту введите /protected off"
}
, {
"ProtectedOnPlayer", "У игрока включена защита после вайпа! Вы не можете наносить урон по игроку"
}
, {
"OwnerProtected", "Даже не старайтесь! Игрок и его постройки защищены.\nПриходите немного позже"
}
, {
"ProtectedAlreadyOff", "\tВы больше не состоите под защитой после вайпа."
}
, {
"CmdHelp", "<size=16>Players Protected by RustPlugin.ru</size>\n{0}"
}
, {
"CmdHelpAdmin", "<size=16>Команды администратора:</size>\n\tВы можете как администратор сделать \n\tручной вайп данных, команда: /protected wipe\n\tТак же вы можете включить себе защиту: /protected on \n\ttime (в секундах)"
}
, {
"ProtectedAlready", "\tВы состоите под защитой, до окончения: {0}\n\tЧто бы отключить защиту введите /protected off"
}
, {
"CmdProtectedOff", "Вы успешно отключили защиту от рейда.Теперь вы можете наносить урон по постройкам и по игрокам, вы и Ваши постройки больше не защищены"
}
, {
"DisabledProcOnBuildingBlock", "Внимание! Вы вошли в чужую зону шкафа в какой вы не авторизованы, ваша защита отключена"
}
, {
"OutInBuildingBlock", "Внимание! Вы покинули чужую зону шкафа или авторизовались в шкафу, защита активирована"
}
,
}
;
}
}