C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
TODO:
- Add command to see who has reserved.slot permission
- Add option to automatically make admin reserved
*/
using System;
using System.Collections.Generic;
using System.Linq;
namespace Oxide.Plugins
{
[Info("Reserved", "Wulf/lukespragg", "1.1.0", ResourceId = 0)]
[Description("Allows players with permission to always be able to connect")]
class Reserved : CovalencePlugin
{
// Do NOT edit this file, instead edit Reserved.json in oxide/config and Reserved.en.json in the oxide/lang directory,
// or create a new language file for another language using the 'en' file as a default
#region Configuration
bool AutoAdminSlots => GetConfig("AutoAdminSlots", true);
bool DynamicSlots => GetConfig("DynamicSlots", false);
//bool IgnorePlayerLimit => GetConfig("IgnorePlayerLimit", false);
bool KickForReserved => GetConfig("KickForReserved", false);
int ReservedSlots => GetConfig("ReservedSlots", 5);
protected override void LoadDefaultConfig()
{
Config["AutoAdminSlots"] = AutoAdminSlots;
Config["DynamicSlots"] = DynamicSlots;
//Config["IgnorePlayerLimit"] = IgnorePlayerLimit;
Config["KickForReserved"] = KickForReserved;
Config["ReservedSlots"] = ReservedSlots;
SaveConfig();
}
#endregion
#region Localization
void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
{"KickedForReserved", "Kicked for reserved slot"},
{"ReservedSlotsOnly", "Only reserved slots available"},
{"SlotsNowAvailable", "{total} slot(s) now available"}
}, this);
}
#endregion
#region Initialization
void Init()
{
LoadDefaultConfig();
LoadDefaultMessages();
permission.RegisterPermission("reserved.slot", this);
}
void OnServerInitialized()
{
if (!DynamicSlots) return;
var slotCount = players.All.Count(player => player.HasPermission("reserved.slot"));
Config["ReservedSlots"] = slotCount;
SaveConfig();
Puts(Lang("SlotsNowAvailable").Replace("{total}", slotCount.ToString()));
}
#endregion
#region Reserved Check
string CheckForSlots(int currentPlayers, int maxPlayers, string id)
{
if (AutoAdminSlots && IsAdmin(id))
if ((currentPlayers + ReservedSlots) >= maxPlayers && !HasPermission(id, "reserved.slot"))
return Lang("ReservedSlotsOnly", id);
//if (IgnorePlayerLimit) return null;
/*if (currentPlayers >= maxPlayers)
{
// TODO: Kick random player with no reserved slot
var targets = players.Online.ToArray();
var target = players[(new Random()).Next(0, targets.Length)];
if (!target.HasPermission("reserved.slot")) target.Kick(Lang("KickedForReserved", target.Id));
return null;
}*/
return null;
}
#if HURTWORLD
object CanClientLogin(PlayerSession session)
{
return CheckForSlots(GameManager.Instance.GetPlayerCount(), GameManager.Instance.ServerConfig.MaxPlayers, session.SteamId.ToString());
}
#endif
#if REIGNOFKINGS
object OnUserApprove(CodeHatch.Engine.Core.Networking.ConnectionLoginData data)
{
var playerCount = CodeHatch.Engine.Networking.Server.PlayerCount;
var playerLimit = CodeHatch.Engine.Networking.Server.PlayerLimit;
return CheckForSlots(playerCount, playerLimit, data.PlayerId.ToString()) != null ? (object)ConnectionError.LimitedPlayers : null;
}
#endif
#if RUST
object CanClientLogin(Network.Connection connection)
{
return CheckForSlots(BasePlayer.activePlayerList.Count, ConVar.Server.maxplayers, connection.userid.ToString());
}
#endif
#if RUSTLEGACY
object CanClientLogin(ClientConnection connection)
{
return CheckForSlots(PlayerClient.All.Count, global::server.maxplayers, connection.UserID.ToString());
}
#endif
#endregion
#region Helpers
T GetConfig<T>(string name, T value) => Config[name] == null ? value : (T)Convert.ChangeType(Config[name], typeof(T));
string Lang(string key, string userId = null) => lang.GetMessage(key, this, userId);
bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
bool IsAdmin(string id) => permission.UserHasGroup(id, "admin");
#endregion
}
}