C#:
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using System.Text;
using System.Collections.Generic;
using System;
namespace Oxide.Plugins
{
[Info("DeathLockout", "rustmods.ru", "1.1.0")]
[Description("Блокировка входа на сервер после смерти")]
public class DeathLockout : RustPlugin
{
private class Configuration
{
public static Configuration GetNewConfiguration()
{
return new Configuration
{
generalSettings = new GeneralSettings()
{
settingIQChat = new GeneralSettings.IQChatSetting()
{
customAvatar = "0",
customPrefix = LanguageEn ? "[<color=#eb4034>LIFE</color>]\n" : "[<color=#eb4034>ЖИЗНЬ</color>]\n",
uiAlertUse = false,
}
},
lifePresetDefault = new LifeController()
{
kickSeconds = 15,
lifeAmount = 1,
triggerBlock = new LifeController.TriggerBlock()
{
Player = true,
Suicide = true,
NPC = false,
Animal = false,
AllTrigger = false,
}
}
};
}
internal class LifeController
{
[JsonProperty(LanguageEn ? "" : "На смерть от чего будет распространяться блокировка входа")]
public TriggerBlock triggerBlock = new TriggerBlock();
[JsonProperty(LanguageEn ? "" : "Количество допустимых смертей до блокировки входа на сервер")]
public Int32 lifeAmount;
[JsonProperty(LanguageEn ? "" : "Через сколько кикать игрока после смерти")]
public Int32 kickSeconds;
internal class TriggerBlock
{
[JsonProperty(LanguageEn ? "" : "Игроки (true - да/false - нет)")]
public Boolean Player;
[JsonProperty(LanguageEn ? "" : "NPC (true - да/false - нет)")]
public Boolean NPC;
[JsonProperty(LanguageEn ? "" : "Животные (true - да/false - нет)")]
public Boolean Animal;
[JsonProperty(LanguageEn ? "" : "Суицид (true - да/false - нет)")]
public Boolean Suicide;
[JsonProperty(LanguageEn ? "" : "Абсолютно любая смерть (true - да/false - нет)")]
public Boolean AllTrigger;
}
}
[JsonProperty(LanguageEn ? "" : "Настройка управления блокировкой входа после смерти")]
public LifeController lifePresetDefault = new LifeController();
[JsonProperty(LanguageEn ? "" : "Общая настройка плагина")]
public GeneralSettings generalSettings = new GeneralSettings();
internal class GeneralSettings
{
internal class IQChatSetting
{
[JsonProperty(LanguageEn? "IQChat : Custom avatar in the chat (If required)": "IQChat : Кастомный аватар в чате (Если требуется)")]
public String customAvatar;
[JsonProperty(LanguageEn? "IQChat : Use UI notifications": "IQChat : Использовать UI уведомления")]
public Boolean uiAlertUse;
[JsonProperty(LanguageEn ? "IQChat : Custom prefix in chat" : "IQChat : Кастомный префикс в чате")]
public String customPrefix;
}
[JsonProperty(LanguageEn ? "Setting up IQChat (If installed)" : "Настройка IQChat (Если установлен)")]
public IQChatSetting settingIQChat = new IQChatSetting();
}
}
private Object CanUserLogin(String name, String id)
{
if (permission.UserHasPermission(id, PermissionIgnore)) return null;
UInt64 userID = UInt64.Parse(id);
if (PlayerLocked.ContainsKey(userID) && PlayerLocked[userID] >= config.lifePresetDefault.lifeAmount)
return GetLang("TITLE_KICK", id);
return null;
}
private static StringBuilder sb = new StringBuilder();
private void OnNewSave(string filename)
{
if(PlayerLocked != null)
PlayerLocked.Clear();
WriteData();
Puts(LanguageEn ? "A WIPE has been detected. The data file has been automatically cleared." : "Обнаружен WIPE. Дата-файл был очищен автоматически.");
}
private Boolean IsDeadTrigger(BasePlayer player,HitInfo info)
{
if (permission.UserHasPermission(player.UserIDString, PermissionIgnore)) return false;
if (IsDuel(player.userID)) return false;
BaseEntity Initiator = info.Initiator;
if (config.lifePresetDefault.triggerBlock.AllTrigger)
return true;
if(config.lifePresetDefault.triggerBlock.NPC)
if (Initiator is ScientistNPC || Initiator is HumanNPC)
return true;
if(config.lifePresetDefault.triggerBlock.Animal)
if (Initiator is BaseAnimalNPC)
return true;
if(config.lifePresetDefault.triggerBlock.Player)
if (Initiator is BasePlayer && info.InitiatorPlayer != null && !info.InitiatorPlayer.IsNpc)
return true;
if(config.lifePresetDefault.triggerBlock.Suicide)
if (info.InitiatorPlayer != null && info.InitiatorPlayer == player)
return true;
return false;
}
private static Configuration config = new Configuration();
private new void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<String, String>
{
["DL_TITLE_KICK"] = "You have exhausted your life count.\nYou will be able to join the next WIPE.",
["DL_TITLE_ALERT_LIFE"] = "You have died and used up one life, you have {0} lives remaining.\nIf you run out of lives - you will only be able to join on the next WIPE."
}, this);
lang.RegisterMessages(new Dictionary<String, String>
{
["DL_TITLE_KICK"] = "Вы исчерпали количество жизней.\nВы сможете зайти на следующий WIPE",
["DL_TITLE_ALERT_LIFE"] = "Вы погибли и истратили свою жизнь, у вас осталось {0} жизней\nЕсли жизни кончатся - вы сможете зайти только на следующий WIPE",
}, this, "ru");
}
private void DeathPlayer(BasePlayer player)
{
if(!PlayerLocked.ContainsKey(player.userID))
PlayerLocked.Add(player.userID, 1);
if (PlayerLocked[player.userID] < config.lifePresetDefault.lifeAmount)
{
Int32 LifeAmount = config.lifePresetDefault.lifeAmount - PlayerLocked[player.userID];
PlayerLocked[player.userID]++;
SendChat(GetLang("DL_TITLE_ALERT_LIFE", player.UserIDString, LifeAmount), player);
return;
}
SendChat(GetLang("DL_TITLE_KICK", player.UserIDString), player);
player.Invoke(() =>
{
if(player.IsAlive())
player.Hurt(1000, Rust.DamageType.Suicide);
player.Kick(GetLang("DL_TITLE_KICK", player.UserIDString));
}, config.lifePresetDefault.kickSeconds);
}
private void Init() => ReadData();
private String GetLang(String LangKey, String userID = null, params System.Object[] args)
{
sb.Clear();
if (args == null) return lang.GetMessage(LangKey, this, userID);
sb.AppendFormat(lang.GetMessage(LangKey, this, userID), args);
return sb.ToString();
}
private void WriteData() => Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject("DeathLockout/InformationUsers", PlayerLocked);
private void SendChat(String Message, BasePlayer player, ConVar.Chat.ChatChannel channel = ConVar.Chat.ChatChannel.Global)
{
if (IQChat)
if (config.generalSettings.settingIQChat.uiAlertUse)
IQChat?.Call("API_ALERT_PLAYER_UI", player, Message);
else IQChat?.Call("API_ALERT_PLAYER", player, Message,config.generalSettings.settingIQChat.customPrefix,config.generalSettings.settingIQChat.customAvatar);
else player.SendConsoleCommand("chat.add", channel, 0, Message);
}
[PluginReference] Plugin IQChat, EventHelper, Battles, Duel, OneVSOne, ArenaTournament;
private Dictionary<UInt64, Int32> PlayerLocked = new Dictionary<UInt64, Int32>();
/// <summary>
/// - Добавлено разрешение, с помощью которого будут игнорироваться игроки при смерти - deathlockout.ignore
/// </summary>
private const Boolean LanguageEn = false;
private void OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (player == null) return;
if (!player.userID.IsSteamId() || player.IsNpc) return;
if (info == null) return;
if (IsDeadTrigger(player, info))
DeathPlayer(player);
}
public Boolean IsDuel(UInt64 userID)
{
if (EventHelper)
{
if ((Boolean)EventHelper.CallHook("EMAtEvent", userID))
return true;
}
if (Battles) return (Boolean)Battles?.Call("IsPlayerOnBattle", userID);
if (Duel) return (Boolean)Duel?.Call("IsPlayerOnActiveDuel", BasePlayer.FindByID(userID));
if (OneVSOne) return (Boolean)OneVSOne?.Call("IsEventPlayer", BasePlayer.FindByID(userID));
if (ArenaTournament) return ArenaTournament.Call<Boolean>("IsOnTournament", userID);
return false;
}
private const String PermissionIgnore = "deathlockout.ignore";
void OnServerInitialized()
{
if (!permission.PermissionExists(PermissionIgnore, this))
permission.RegisterPermission(PermissionIgnore, this);
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
if (PlayerLocked.ContainsKey(player.userID) && PlayerLocked[player.userID] >= config.lifePresetDefault.lifeAmount)
{
if (player.IsAlive())
player.Hurt(1000, Rust.DamageType.Suicide);
player.Kick(GetLang("DL_TITLE_KICK", player.UserIDString));
}
}
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
private void ReadData() => PlayerLocked = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<Dictionary<UInt64, Int32>>("DeathLockout/InformationUsers");
protected override void SaveConfig() => Config.WriteObject(config);
private void Unload() => WriteData();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
}
catch
{
PrintWarning("Ошибка #2178563" + $"чтения конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
}
}