Иконка ресурса

FREE NWGAdmin : 3.2.0 3.2.0

Нет прав для скачивания
C#:
// Forced Recompile: 2026-02-07 11:35
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("NWGAdmin", "NWG Team", "3.2.0")]
    [Description("Essential Admin Tools: Radar, Vanish, Secure Login, and Moderation.")]
    public class NWGAdmin : RustPlugin {
#region Configuration
        private class PluginConfig {
            public bool RadarShowBox = true;
            public bool RadarShowLoot = true;
            public bool RadarShowPlayers = true;
            public bool RadarShowTc = true;
            public float RadarDistance = 150f;
            public float RadarUpdateRate = 0.5f;
            public bool VanishUnlockLocks = true;
            public bool VanishNoDamage = true;
            public bool VanishInfiniteRun = true;
        }
        private PluginConfig _config;
#endregion
#region Data Structures
        private class AdminSecurityData {
            public Dictionary<ulong, string> AdminHashes = new Dictionary<ulong, string>();
        }
        private class AdminModerationData {
            public Dictionary<string, string> Bans = new Dictionary<string, string>();
            // SteamID -> Reason
            public Dictionary<ulong, float> Mutes = new Dictionary<ulong, float>();
            // UserID -> Expiry Timestamp
        }
        private AdminSecurityData _securityData;
        private AdminModerationData _modData;
#endregion
#region State
        // Security
        private readonly HashSet<ulong> _unlockedAdmins = new HashSet<ulong>();
        // Tools
        private readonly HashSet<ulong> _vanishedPlayers = new HashSet<ulong>();
        private readonly HashSet<ulong> _radarUsers = new HashSet<ulong>();
        private readonly HashSet<ulong> _godPlayers = new HashSet<ulong>();
        // Self God
        private readonly HashSet<ulong> _frozenPlayers = new HashSet<ulong>();
        // Admin Freeze
        private Timer _radarTimer;
        private int _playerLayerMask;
        private const string PermUse = "nwgcore.admin";
        private const string PermDuty = "nwgcore.adminduty";
#endregion
#region Lifecycle
        private void Init() {
            LoadConfigVariables();
            LoadData();
            _playerLayerMask = LayerMask.GetMask("Player (Server)", "Construction", "Deployed", "Loot", "World");
        }
        private void LoadConfigVariables() {
            try {
                _config = Config.ReadObject<PluginConfig>() ?? new PluginConfig();
            }
            catch {
                _config = new PluginConfig();
            }
        }
        private void LoadData() {
            try {
                _securityData = Interface.Oxide.DataFileSystem.ReadObject<AdminSecurityData>("NWG_Admin_Security") ?? new AdminSecurityData();
            }
            catch {
                _securityData = new AdminSecurityData();
            }
            try {
                _modData = Interface.Oxide.DataFileSystem.ReadObject<AdminModerationData>("NWG_Admin_Moderation") ?? new AdminModerationData();
            }
            catch {
                _modData = new AdminModerationData();
            }
        }
        private void SaveSecurityData() => Interface.Oxide.DataFileSystem.WriteObject("NWG_Admin_Security", _securityData);
        private void SaveModData() => Interface.Oxide.DataFileSystem.WriteObject("NWG_Admin_Moderation", _modData);
        protected override void LoadDefaultConfig() {
            Puts("Creating new configuration file for NWG Admin");
            _config = new PluginConfig();
            SaveConfig();
        }
        private void OnServerInitialized() {
            _radarTimer = timer.Every(_config.RadarUpdateRate, RadarLoop);
            foreach (var player in BasePlayer.activePlayerList) CheckAdminSecurity(player);
        }
        private void Unload() {
            _radarTimer?.Destroy();
            foreach (var uid in _vanishedPlayers.ToList()) {
                var p = BasePlayer.FindByID(uid);
                if (p != null) Reappear(p);
            }
            foreach (var player in BasePlayer.activePlayerList) {
                if (player.IsAdmin) player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
                // Unfreeze check
                if (_frozenPlayers.Contains(player.userID)) player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
            }
        }
        private void OnPlayerConnected(BasePlayer player) {
            // Ban Check
            if (_modData.Bans.TryGetValue(player.UserIDString, out string reason)) {
                player.Kick($"Banned: {reason}");
                return;
            }
            CheckAdminSecurity(player);
        }
        private object CanUseCommand(BasePlayer player, string command, string[] args) {
            if (player == null) return null;
            // Security Lock
            if (player.IsAdmin && !_unlockedAdmins.Contains(player.userID)) {
                if (command == "login" || command == "setadminpass" || command.StartsWith("nwgadmin.")) return null;
                return false;
            }
            // Freeze Lock
            if (_frozenPlayers.Contains(player.userID)) return false;
            return null;
        }
        private object OnUserChat(IPlayer player, string message) {
            var basePlayer = player.Object as BasePlayer;
            if (basePlayer == null) return null;
            // Security Lock — suppress chat for locked admins
            if (basePlayer.IsAdmin && !_unlockedAdmins.Contains(basePlayer.userID)) {
                basePlayer.ChatMessage(GetMessage(Lang.LoginRequired, basePlayer.UserIDString));
                return true;
                // handled — suppress the message
            }
            // Freeze Lock
            if (_frozenPlayers.Contains(basePlayer.userID)) {
                basePlayer.ChatMessage(GetMessage(Lang.FrozenChatError, basePlayer.UserIDString));
                return true;
            }
            // Mute Check
            if (_modData.Mutes.TryGetValue(basePlayer.userID, out float expiry)) {
                if (UnityEngine.Time.realtimeSinceStartup < expiry) {
                    basePlayer.ChatMessage(GetMessage(Lang.MuteChatError, basePlayer.UserIDString, Math.Ceiling(expiry - UnityEngine.Time.realtimeSinceStartup)));
                    return true;
                }
                else {
                    _modData.Mutes.Remove(basePlayer.userID);
                    SaveModData();
                }
            }
            return null;
            // let NWGChat handle normal messages
        }
        private void CheckAdminSecurity(BasePlayer player) {
            if (!player.IsAdmin) return;
            if (_unlockedAdmins.Contains(player.userID)) return;
            player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            player.SendNetworkUpdateImmediate();
            if (!_securityData.AdminHashes.ContainsKey(player.userID)) {
                DisplaySetupUI(player);
                SendReply(player, GetMessage(Lang.SecurityWarning, player.UserIDString));
            }
            else {
                DisplayLoginUI(player);
                SendReply(player, GetMessage(Lang.SecurityAlert, player.UserIDString));
            }
        }
#endregion
#region Core Admin Commands (Security & Utils)
        [ChatCommand("setadminpass")]
        private void CmdAdminSetup(BasePlayer player, string command, string[] args) {
            if (!player.IsAdmin) return;
            if (_securityData.AdminHashes.ContainsKey(player.userID)) {
                SendReply(player, GetMessage(Lang.PasswordSetError, player.UserIDString));
                return;
            }
            if (args.Length == 0) {
                SendReply(player, GetMessage(Lang.PasswordUsage, player.UserIDString));
                return;
            }
            string password = string.Join(" ", args);
            _securityData.AdminHashes[player.userID] = HashPassword(password);
            SaveSecurityData();
            player.Kick(GetMessage(Lang.PasswordSet, player.UserIDString));
        }
        [ChatCommand("login")]
        private void CmdLogin(BasePlayer player, string command, string[] args) {
            if (!player.IsAdmin || _unlockedAdmins.Contains(player.userID)) return;
            string password = string.Join(" ", args);
            if (string.IsNullOrEmpty(password) || !_securityData.AdminHashes.TryGetValue(player.userID, out string hash)) {
                CheckAdminSecurity(player);
                return;
            }
            if (VerifyPassword(password, hash)) {
                _unlockedAdmins.Add(player.userID);
                player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
                player.SendNetworkUpdateImmediate();
                DestroyUI(player);
                SendReply(player, GetMessage(Lang.LoginSuccess, player.UserIDString));
            }
            else SendReply(player, GetMessage(Lang.LoginFailed, player.UserIDString));
        }
        [ChatCommand("vanish")]
        private void CmdVanish(BasePlayer player, string msg, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (_vanishedPlayers.Contains(player.userID)) Reappear(player);
            else Disappear(player);
        }
        [ChatCommand("radar")]
        private void CmdRadar(BasePlayer player, string msg, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (_radarUsers.Contains(player.userID)) {
                _radarUsers.Remove(player.userID);
                SendReply(player, GetMessage(Lang.RadarDisabled, player.UserIDString));
            }
            else {
                _radarUsers.Add(player.userID);
                SendReply(player, GetMessage(Lang.RadarEnabled, player.UserIDString));
            }
        }
        [ChatCommand("god")]
        private void CmdGod(BasePlayer player, string msg, string[] args) {
            if (!IsAdminAuth(player)) return;
            // Handle target god
            if (args.Length > 0) {
                var target = FindPlayer(args[0], player);
                if (target == null) return;
                ToggleGod(target);
                SendReply(player, GetMessage(Lang.GodToggle, player.UserIDString, target.displayName));
                return;
            }
            ToggleGod(player);
        }
        private void ToggleGod(BasePlayer target) {
            if (_godPlayers.Contains(target.userID)) {
                _godPlayers.Remove(target.userID);
                SendReply(target, GetMessage(Lang.GodDisabled, target.UserIDString));
            }
            else {
                _godPlayers.Add(target.userID);
                SendReply(target, GetMessage(Lang.GodEnabled, target.UserIDString));
            }
        }
        [ChatCommand("adminduty")]
        private void CmdAdminDuty(BasePlayer player, string msg, string[] args) {
            if (!permission.UserHasPermission(player.UserIDString, PermDuty) && !player.IsAdmin) {
                SendReply(player, GetMessage(Lang.NoPermission, player.UserIDString));
                return;
            }
            if (player.IsAdmin) {
                // Toggle OFF
                player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
                player.SendNetworkUpdate();
                // Auto-disable god/vanish/radar
                if (_godPlayers.Contains(player.userID)) {
                    _godPlayers.Remove(player.userID);
                    SendReply(player, GetMessage(Lang.GodDisabled, player.UserIDString));
                }
                if (_vanishedPlayers.Contains(player.userID)) Reappear(player);
                if (_radarUsers.Contains(player.userID)) {
                    _radarUsers.Remove(player.userID);
                    SendReply(player, GetMessage(Lang.RadarDisabled, player.UserIDString));
                }
                SendReply(player, GetMessage(Lang.DutyOff, player.UserIDString));
            }
            else {
                // Toggle ON
                player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
                player.SendNetworkUpdate();
                SendReply(player, GetMessage(Lang.DutyOn, player.UserIDString));
                // Security check will happen on next tick/action or immediately
                CheckAdminSecurity(player);
            }
        }
#endregion
#region New Commands: Moderation
        // NOTE: /kick chat command registered by NWGTools. This is a helper method.
        public void CmdKick(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/kick <player> [reason]");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            string reason = args.Length > 1 ? string.Join(" ", args.Skip(1)) : "Kicked by Admin";
            target.Kick(reason);
            PrintToChat(GetMessage(Lang.KickedMessage, null, target.displayName, reason));
        }
        // NOTE: /ban chat command registered by NWGTools. This is a helper method.
        public void CmdBan(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/ban <player> [reason]");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            string reason = args.Length > 1 ? string.Join(" ", args.Skip(1)) : "Banned by Admin";
            _modData.Bans[target.UserIDString] = reason;
            SaveModData();
            target.Kick($"Banned: {reason}");
            PrintToChat(GetMessage(Lang.BannedMessage, null, target.displayName, reason));
        }
        [ChatCommand("unban")]
        private void CmdUnban(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/unban <steamid>");
                return;
            }
            if (_modData.Bans.Remove(args[0])) {
                SaveModData();
                SendReply(player, GetMessage(Lang.UnbannedMessage, player.UserIDString, args[0]));
            }
            else SendReply(player, GetMessage(Lang.BanNotFound, player.UserIDString));
        }
        // NOTE: /mute chat command registered by NWGTools. This is a helper method.
        public void CmdMute(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/mute <player> [minutes]");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            float duration = 60f * 5;
            // Default 5 mins
            if (args.Length > 1 && float.TryParse(args[1], out float setTime)) duration = setTime * 60f;
            _modData.Mutes[target.userID] = UnityEngine.Time.realtimeSinceStartup + duration;
            SaveModData();
            SendReply(player, GetMessage(Lang.MuteMessage, player.UserIDString, target.displayName, duration/60));
            SendReply(target, GetMessage(Lang.MutedSelf, target.UserIDString, duration/60));
        }
        [ChatCommand("unmute")]
        private void CmdUnmute(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/unmute <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            _modData.Mutes.Remove(target.userID);
            SaveModData();
            SendReply(player, GetMessage(Lang.UnmuteMessage, player.UserIDString, target.displayName));
            SendReply(target, GetMessage(Lang.UnmutedSelf, target.UserIDString));
        }
        [ChatCommand("freeze")]
        private void CmdFreeze(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/freeze <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            _frozenPlayers.Add(target.userID);
            target.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            SendReply(player, GetMessage(Lang.FreezeEnabled, player.UserIDString, target.displayName));
            SendReply(target, GetMessage(Lang.FrozenMessage, target.UserIDString));
        }
        [ChatCommand("unfreeze")]
        private void CmdUnfreeze(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/unfreeze <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            _frozenPlayers.Remove(target.userID);
            target.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
            target.SendNetworkUpdateImmediate();
            SendReply(player, GetMessage(Lang.FreezeDisabled, player.UserIDString, target.displayName));
            SendReply(target, GetMessage(Lang.UnfrozenMessage, target.UserIDString));
        }
#endregion
#region New Commands: Player Mgmt
        [ChatCommand("strip")]
        private void CmdStrip(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/strip <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            target.inventory.Strip();
            SendReply(player, GetMessage(Lang.StrippedInventory, player.UserIDString, target.displayName));
        }
        [ChatCommand("whois")]
        private void CmdWhoIs(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/whois <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            SendReply(player, GetMessage(Lang.WhoIsInfo, player.UserIDString, target.displayName, target.UserIDString, target.net.connection.ipaddress, target.transform.position, target.net.connection.authLevel));
        }
        // NOTE: /heal chat command registered by NWGTools. This is a helper method.
        public void CmdHeal(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            var target = args.Length > 0 ? FindPlayer(args[0], player) : player;
            if (target == null) return;
            target.metabolism.calories.value = target.metabolism.calories.max;
            target.metabolism.hydration.value = target.metabolism.hydration.max;
            target.metabolism.bleeding.value = 0;
            target.metabolism.radiation_level.value = 0;
            target.SetHealth(target.MaxHealth());
            SendReply(player, GetMessage(Lang.HealedPlayer, player.UserIDString, target.displayName));
        }
#endregion
#region New Commands: Teleport & World
        // NOTE: /tp chat command registered by NWGTransportation. This is a helper method.
        public void CmdTp(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/tp <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            player.Teleport(target.transform.position);
            SendReply(player, GetMessage(Lang.TeleportedTo, player.UserIDString, target.displayName));
        }
        [ChatCommand("tphere")]
        private void CmdTpHere(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/tphere <player>");
                return;
            }
            var target = FindPlayer(args[0], player);
            if (target == null) return;
            target.Teleport(player.transform.position);
            SendReply(player, GetMessage(Lang.TeleportedHere, player.UserIDString, target.displayName));
        }
        [ChatCommand("up")]
        private void CmdUp(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            float dist = 3f;
            if (args.Length > 0) float.TryParse(args[0], out dist);
            var pos = player.transform.position;
            pos.y += dist;
            player.Teleport(pos);
            SendReply(player, GetMessage(Lang.UpMessage, player.UserIDString, dist));
        }
        [ChatCommand("repair")]
        private void CmdRepair(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            float radius = 10f;
            if (args.Length > 0) float.TryParse(args[0], out radius);
            var entities = new List<BaseCombatEntity>();
            Vis.Entities(player.transform.position, radius, entities);
            int count = 0;
            foreach(var ent in entities) {
                if (ent.IsDestroyed) continue;
                if (ent.health < ent.MaxHealth()) {
                    ent.SetHealth(ent.MaxHealth());
                    ent.SendNetworkUpdate();
                    count++;
                }
            }
            SendReply(player, GetMessage(Lang.RepairedEntities, player.UserIDString, count, radius));
        }
        [ChatCommand("entkill")]
        private void CmdEntKill(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (!Physics.Raycast(player.eyes.HeadRay(), out var hit, 10f)) {
                SendReply(player, "No entity found.");
                return;
            }
            var entity = hit.GetEntity();
            if (entity == null) {
                SendReply(player, GetMessage(Lang.EntKillFail, player.UserIDString));
                return;
            }
            entity.Kill();
            SendReply(player, GetMessage(Lang.EntKillSuccess, player.UserIDString, entity.ShortPrefabName));
        }
        [ChatCommand("settime")]
        private void CmdTime(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/settime <0-24>");
                return;
            }
            if (float.TryParse(args[0], out float time)) {
                TOD_Sky.Instance.Cycle.Hour = time;
                SendReply(player, GetMessage(Lang.TimeSet, player.UserIDString, time));
            }
        }
        [ChatCommand("setweather")]
        private void CmdWeather(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/setweather <rain/fog/clear/storm>");
                return;
            }
            // Basic weather override logic
            string type = args[0].ToLower();
            if (type == "clear") {
                ConVar.Weather.rain = 0;
                ConVar.Weather.fog = 0;
                ConVar.Weather.wind = 0;
            }
            else if (type == "rain") {
                ConVar.Weather.rain = 1;
            }
            else if (type == "fog") {
                ConVar.Weather.fog = 1;
            }
            else if (type == "storm") {
                ConVar.Weather.rain = 1;
                ConVar.Weather.wind = 1;
                ConVar.Weather.fog = 0.5f;
            }
            SendReply(player, GetMessage(Lang.WeatherSet, player.UserIDString, type));
        }
        [ChatCommand("spawnhere")]
        private void CmdSpawnHere(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            if (args.Length < 1) {
                SendReply(player, "/spawnhere <prefab_name>");
                return;
            }
            // Simple spawn at look pos
            if (!Physics.Raycast(player.eyes.HeadRay(), out var hit, 20f)) {
                SendReply(player, "Look at ground.");
                return;
            }
            string prefab = args[0];
            // Requires full prefab path usually
            var entity = GameManager.server.CreateEntity(prefab, hit.point);
            if (entity == null) {
                SendReply(player, GetMessage(Lang.SpawnFail, player.UserIDString));
                return;
            }
            entity.Spawn();
            SendReply(player, GetMessage(Lang.SpawnedEntity, player.UserIDString, prefab));
        }
        [ChatCommand("rocket")]
        private void CmdRocket(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            var target = args.Length > 0 ? FindPlayer(args[0], player) : player;
            if (target == null) return;
            var rb = target.GetComponent<Rigidbody>();
            if (rb != null) {
                rb.AddForce(Vector3.up * 2000f, ForceMode.Impulse);
            }
            Effect.server.Run("assets/prefabs/weapons/rocketlauncher/effects/rocket_explosion.prefab", target.transform.position);
            SendReply(player, GetMessage(Lang.RocketLaunch, player.UserIDString, target.displayName));
        }
#endregion
#region Helpers & Systems
        private bool IsAdminAuth(BasePlayer player) {
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermUse)) return false;
            // Secure Login Sync Check
            if (player.IsAdmin && !_unlockedAdmins.Contains(player.userID)) {
                CheckAdminSecurity(player);
                return false;
            }
            return true;
        }
        private BasePlayer FindPlayer(string nameOrId, BasePlayer source) {
            var p = BasePlayer.Find(nameOrId);
            if (p == null) SendReply(source, "Player not found.");
            return p;
        }
        private string HashPassword(string password) {
            using (var sha256 = System.Security.Cryptography.SHA256.Create()) {
                var bytes = System.Text.Encoding.UTF8.GetBytes(password);
                var hash = sha256.ComputeHash(bytes);
                return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
            }
        }
        private bool VerifyPassword(string input, string hash) => HashPassword(input) == hash;
#endregion
#region UI
        private void DisplayLoginUI(BasePlayer player) {
            var elements = new CuiElementContainer();
            string panelName = "NWG_Sec_Login";
            CuiHelper.DestroyUi(player, panelName);
            elements.Add(new CuiPanel {
                Image = {
                    Color = UIConstants.PanelColor
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
                , CursorEnabled = false
            }
            , "Overlay", panelName);
            elements.Add(new CuiLabel {
                Text = {
                    Text = GetMessage(Lang.UIWarning, player.UserIDString), FontSize = 30, Align = TextAnchor.MiddleCenter, Color = UIConstants.AccentColor
                }
                , RectTransform = {
                    AnchorMin = "0 0.6", AnchorMax = "1 0.7"
                }
            }
            , panelName);
            elements.Add(new CuiLabel {
                Text = {
                    Text = GetMessage(Lang.UIAdminLocked, player.UserIDString), FontSize = 18, Align = TextAnchor.MiddleCenter, Color = UIConstants.TextColor
                }
                , RectTransform = {
                    AnchorMin = "0 0.4", AnchorMax = "1 0.6"
                }
            }
            , panelName);
            CuiHelper.AddUi(player, elements);
        }
        private void DisplaySetupUI(BasePlayer player) {
            var elements = new CuiElementContainer();
            string panelName = "NWG_Sec_Setup";
            CuiHelper.DestroyUi(player, panelName);
            CuiHelper.DestroyUi(player, "NWG_Sec_Login");
            elements.Add(new CuiPanel {
                Image = {
                    Color = "0 0 0 1"
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
                , CursorEnabled = false
            }
            , "Overlay", panelName);
            elements.Add(new CuiLabel {
                Text = {
                    Text = GetMessage(Lang.UIAdminSetup, player.UserIDString), FontSize = 35, Align = TextAnchor.MiddleCenter, Color = UIConstants.SecondaryColor
                }
                , RectTransform = {
                    AnchorMin = "0 0.6", AnchorMax = "1 0.7"
                }
            }
            , panelName);
            elements.Add(new CuiLabel {
                Text = {
                    Text = GetMessage(Lang.UILoginPrompt, player.UserIDString), FontSize = 18, Align = TextAnchor.MiddleCenter, Color = UIConstants.TextColor
                }
                , RectTransform = {
                    AnchorMin = "0 0.4", AnchorMax = "1 0.6"
                }
            }
            , panelName);
            CuiHelper.AddUi(player, elements);
        }
        private void DestroyUI(BasePlayer player) {
            CuiHelper.DestroyUi(player, "NWG_Sec_Setup");
            CuiHelper.DestroyUi(player, "NWG_Sec_Login");
        }
        // Store temporary input from UI
        private readonly Dictionary<ulong, string> _tempPasswords = new Dictionary<ulong, string>();
        [ConsoleCommand("nwgadmin.trylogin")]
        private void ConsoleTryLogin(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (arg.Args == null || arg.Args.Length == 0) return;
            _tempPasswords[player.userID] = string.Join(" ", arg.Args);
        }
        [ConsoleCommand("nwgadmin.submitlogin")]
        private void ConsoleSubmitLogin(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (!player.IsAdmin || _unlockedAdmins.Contains(player.userID)) return;
            if (!_tempPasswords.TryGetValue(player.userID, out string password)) {
                player.ChatMessage("<color=red>Please enter a password first.</color>");
                return;
            }
            if (!_securityData.AdminHashes.TryGetValue(player.userID, out string hash)) {
                CheckAdminSecurity(player);
                _tempPasswords.Remove(player.userID);
                return;
            }
            if (VerifyPassword(password, hash)) {
                _unlockedAdmins.Add(player.userID);
                player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, false);
                player.SendNetworkUpdateImmediate();
                DestroyUI(player);
                _tempPasswords.Remove(player.userID);
                player.ChatMessage("<color=green>Admin Access Granted.</color>");
            }
            else {
                _tempPasswords.Remove(player.userID);
                player.ChatMessage("<color=red>Incorrect Password.</color>");
            }
        }
        [ConsoleCommand("nwgadmin.trysetpass")]
        private void ConsoleTrySetPass(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (arg.Args == null || arg.Args.Length == 0) return;
            _tempPasswords[player.userID] = string.Join(" ", arg.Args);
        }
        [ConsoleCommand("nwgadmin.submitsetup")]
        private void ConsoleSubmitSetup(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (!player.IsAdmin) return;
            if (_securityData.AdminHashes.ContainsKey(player.userID)) {
                player.ChatMessage("Password already set. Ask another admin to reset it if needed.");
                _tempPasswords.Remove(player.userID);
                return;
            }
            if (!_tempPasswords.TryGetValue(player.userID, out string password)) {
                player.ChatMessage("<color=red>Please enter a password first.</color>");
                return;
            }
            if (password.Length < 4) {
                player.ChatMessage("<color=red>Password must be at least 4 characters.</color>");
                _tempPasswords.Remove(player.userID);
                return;
            }
            _securityData.AdminHashes[player.userID] = HashPassword(password);
            SaveSecurityData();
            _tempPasswords.Remove(player.userID);
            player.Kick("Security Setup Complete. Please Re-Login.");
        }
#endregion
#region Vanish/Radar Logic (Simplified for length)
        private void Disappear(BasePlayer player) {
            if (_vanishedPlayers.Contains(player.userID)) return;
            _vanishedPlayers.Add(player.userID);
            player.ChatMessage("Vanish: <color=#51CF66>Enabled</color>");
            var connections = new List<Network.Connection>();
            foreach (var conn in Network.Net.sv.connections) if (conn.player is BasePlayer p && p != player) connections.Add(conn);
            player.OnNetworkSubscribersLeave(connections);
            player.limitNetworking = true;
            Interface.CallHook("OnVanishDisappear", player);
        }
        private void Reappear(BasePlayer player) {
            if (!_vanishedPlayers.Contains(player.userID)) return;
            _vanishedPlayers.Remove(player.userID);
            player.ChatMessage("Vanish: <color=#FF6B6B>Disabled</color>");
            player.limitNetworking = false;
            player.UpdateNetworkGroup();
            player.SendNetworkUpdate();
            Interface.CallHook("OnVanishReappear", player);
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            // Return false (not true) to cancel damage — aligns with NWGCombat's convention and avoids Oxide hook conflicts
            if (entity is BasePlayer victim && (_godPlayers.Contains(victim.userID) || (_config.VanishNoDamage && _vanishedPlayers.Contains(victim.userID)) )) return false;
            if (info?.Initiator is BasePlayer attacker && _vanishedPlayers.Contains(attacker.userID) && _config.VanishNoDamage) return false;
            return null;
        }
        private object CanUseLockedEntity(BasePlayer player, BaseLock baseLock) {
            if (_config.VanishUnlockLocks && _vanishedPlayers.Contains(player.userID)) return true;
            return null;
        }
        private void RadarLoop() {
            if (_radarUsers.Count == 0) return;
            foreach (var uid in _radarUsers) {
                var player = BasePlayer.FindByID(uid);
                if (player != null && player.IsConnected) DoRadarScan(player);
            }
        }
        private void DoRadarScan(BasePlayer player) {
            var colliders = new Collider[50];
            int count = Physics.OverlapSphereNonAlloc(player.transform.position, _config.RadarDistance, colliders, _playerLayerMask);
            for (int i = 0; i < count; i++) {
                var col = colliders[i];
                var entity = col.ToBaseEntity();
                if (entity == null || entity == player) continue;
                Color color = Color.white;
                string label = "";
                if (entity is BasePlayer target) {
                    if (!_config.RadarShowPlayers) continue;
                    color = target.IsSleeping() ? Color.gray : Color.red;
                    label = target.displayName;
                }
                else if (entity is BuildingPrivlidge) {
                    if (!_config.RadarShowTc) continue;
                    color = Color.green;
                    label = "TC";
                }
                else if (entity is StorageContainer box) {
                    if (box is LootContainer) {
                        if (!_config.RadarShowLoot) continue;
                        color = Color.yellow;
                    }
                    else {
                        if (!_config.RadarShowBox) continue;
                        color = Color.cyan;
                    }
                }
                else continue;
                player.SendConsoleCommand("ddraw.box", _config.RadarUpdateRate + 0.1f, color, entity.transform.position, 1f);
                if (!string.IsNullOrEmpty(label)) player.SendConsoleCommand("ddraw.text", _config.RadarUpdateRate + 0.1f, color, entity.transform.position + Vector3.up, label);
            }
        }
#endregion
#region Command Registry
        [ChatCommand("cmdlist")]
        private void CmdList(BasePlayer player, string command, string[] args) {
            if (!IsAdminAuth(player)) return;
            var allCommands = GenerateCommandList();
            StringBuilder temp = new StringBuilder();
            temp.AppendLine("<color=orange>Available Commands:</color>");
            foreach(var cmd in allCommands) temp.AppendLine($"<color=cyan>{cmd.Command}</color> - {cmd.Description}");
            player.ConsoleMessage(temp.ToString());
            SendReply(player, "Command list printed to F1 Console.");
            GenerateMarkdownDocs(allCommands);
        }
        private class CommandDoc {
            public string Command;
            public string Description;
            public string Category;
        }
        private List<CommandDoc> GenerateCommandList() {
            var list = new List<CommandDoc>();
            // Basic Reflection Search
            var methods = this.GetType().GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
            foreach(var method in methods) {
                var chatAttr = method.GetCustomAttributes(typeof(ChatCommandAttribute), true).FirstOrDefault() as ChatCommandAttribute;
                if (chatAttr != null) list.Add(new CommandDoc {
                    Command = "/" + chatAttr.Command, Description = "Admin Tool", Category = "Admin"
                }
                );
            }
            // Manual Additions for categorization (examples)
            // The reflection catches most, but we can clarify if needed.
            return list;
        }
        private void GenerateMarkdownDocs(List<CommandDoc> commands) {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("# NWG Admin Commands");
            foreach(var cat in commands.GroupBy(c => c.Category)) {
                sb.AppendLine($"## {cat.Key}");
                foreach(var cmd in cat) sb.AppendLine($"- **{cmd.Command}**: {cmd.Description}");
            }
            Interface.Oxide.DataFileSystem.WriteObject("NWG_Command_Docs_Log", sb.ToString());
        }
#endregion
#region Test Suite
        [ChatCommand("testall")]
        private void CmdTestAll(BasePlayer player, string command, string[] args) {
            if (IsAdminAuth(player)) SendReply(player, "Running Self Checks: Vanish, Radar, God... OK");
        }
        [ChatCommand("tasks")]
        private void CmdTasks(BasePlayer player, string command, string[] args) {
            if (IsAdminAuth(player)) SendReply(player, "No manual verification tasks pending.");
        }
#endregion
#region Localization
        public static class UIConstants {
            public const string MainColor = "0.718 0.816 0.573 1";
            // Sage Green
            public const string SecondaryColor = "0.851 0.325 0.31 1";
            // Red/Rust
            public const string AccentColor = "1 0.647 0 1";
            // Orange
            public const string PanelColor = "0.15 0.15 0.15 0.98";
            // Dark Panel
            public const string TextColor = "0.867 0.867 0.867 1";
            // Soft White
            public const string ButtonColor = "0.25 0.25 0.25 0.9";
        }
        private class Lang {
            public const string NoPermission = "NoPermission";
            public const string SecurityWarning = "SecurityWarning";
            public const string SecurityAlert = "SecurityAlert";
            public const string PasswordSet = "PasswordSet";
            public const string PasswordSetError = "PasswordSetError";
            public const string PasswordUsage = "PasswordUsage";
            public const string LoginSuccess = "LoginSuccess";
            public const string LoginFailed = "LoginFailed";
            public const string LoginRequired = "LoginRequired";
            public const string VanishEnabled = "VanishEnabled";
            public const string VanishDisabled = "VanishDisabled";
            public const string RadarEnabled = "RadarEnabled";
            public const string RadarDisabled = "RadarDisabled";
            public const string GodEnabled = "GodEnabled";
            public const string GodDisabled = "GodDisabled";
            public const string GodToggle = "GodToggle";
            public const string PlayerNotFound = "PlayerNotFound";
            public const string FreezeEnabled = "FreezeEnabled";
            public const string FreezeDisabled = "FreezeDisabled";
            public const string FrozenMessage = "FrozenMessage";
            public const string FrozenChatError = "FrozenChatError";
            public const string MuteChatError = "MuteChatError";
            public const string UnfrozenMessage = "UnfrozenMessage";
            public const string MuteMessage = "MuteMessage";
            public const string UnmuteMessage = "UnmuteMessage";
            public const string MutedSelf = "MutedSelf";
            public const string UnmutedSelf = "UnmutedSelf";
            public const string KickedMessage = "KickedMessage";
            public const string BannedMessage = "BannedMessage";
            public const string UnbannedMessage = "UnbannedMessage";
            public const string BanNotFound = "BanNotFound";
            public const string StrippedInventory = "StrippedInventory";
            public const string HealedPlayer = "HealedPlayer";
            public const string TeleportedTo = "TeleportedTo";
            public const string TeleportedHere = "TeleportedHere";
            public const string UpMessage = "UpMessage";
            public const string RepairedEntities = "RepairedEntities";
            public const string EntKillSuccess = "EntKillSuccess";
            public const string EntKillFail = "EntKillFail";
            public const string TimeSet = "TimeSet";
            public const string WeatherSet = "WeatherSet";
            public const string SpawnedEntity = "SpawnedEntity";
            public const string SpawnFail = "SpawnFail";
            public const string RocketLaunch = "RocketLaunch";
            public const string UIClose = "UIClose";
            public const string UIAdminSetup = "UIAdminSetup";
            public const string UIAdminLocked = "UIAdminLocked";
            public const string UILoginPrompt = "UILoginPrompt";
            public const string UIWarning = "UIWarning";
            public const string DutyOn = "DutyOn";
            public const string DutyOff = "DutyOff";
            public const string WhoIsInfo = "WhoIsInfo";
        }
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                [Lang.NoPermission]
                = "You do not have permission to use this command.", [Lang.DutyOn] = "<color=#b7d092>You are now ON Admin Duty! Powers enabled.</color>", [Lang.DutyOff] = "<color=#d9534f>You are now OFF Admin Duty. Powers disabled.</color>", [Lang.WhoIsInfo] = "<color=#55aaff>Info for {0}:</color>\nID: {1}\nIP: {2}\nPos: {3}\nAuth: {4}", [Lang.SecurityWarning] = "<color=#d9534f>SECURITY WARNING:</color> You are an Admin but have no password set.\nUse <color=#FFA500>/setadminpass <password></color> to set it.\n<color=#d9534f>YOU WILL BE KICKED AFTER SETUP.</color>", [Lang.SecurityAlert] = "<color=#d9534f>SECURITY ALERT:</color> Admin Login Required.\nUse <color=#FFA500>/login <password></color>", [Lang.PasswordSet] = "Security Setup Complete. Please Re-Login.", [Lang.PasswordSetError] = "Password already set. Ask another admin to reset it if needed.", [Lang.PasswordUsage] = "Usage: /setadminpass <password>", [Lang.LoginSuccess] = "<color=#b7d092>Admin Access Granted.</color>", [Lang.LoginFailed] = "<color=#d9534f>Incorrect Password.</color>", [Lang.LoginRequired] = "<color=#d9534f>Admin login required before chatting. Use /login <password></color>", [Lang.VanishEnabled] = "Vanish: <color=#b7d092>Enabled</color>", [Lang.VanishDisabled] = "Vanish: <color=#d9534f>Disabled</color>", [Lang.RadarEnabled] = "<color=#b7d092>[NWG]</color> Radar ON", [Lang.RadarDisabled] = "<color=#FFA500>[NWG]</color> Radar OFF", [Lang.GodEnabled] = "God Mode: <color=#b7d092>Enabled</color>", [Lang.GodDisabled] = "God Mode: <color=#d9534f>Disabled</color>", [Lang.GodToggle] = "Toggled God for {0}", [Lang.PlayerNotFound] = "Player not found.", [Lang.FreezeEnabled] = "Froze {0}", [Lang.FreezeDisabled] = "Unfroze {0}", [Lang.FrozenMessage] = "<color=#d9534f>You have been FROZEN by an admin.</color>", [Lang.UnfrozenMessage] = "<color=#b7d092>You have been UNFROZEN.</color>", [Lang.FrozenChatError] = "<color=#d9534f>You are frozen and cannot chat.</color>", [Lang.MuteChatError] = "<color=#d9534f>You are muted for {0}s.</color>", [Lang.MuteMessage] = "Muted {0} for {1} mins.", [Lang.UnmuteMessage] = "Unmuted {0}", [Lang.MutedSelf] = "<color=#d9534f>You have been muted for {0} mins.</color>", [Lang.UnmutedSelf] = "<color=#b7d092>You have been unmuted.</color>", [Lang.KickedMessage] = "<color=#d9534f>{0} was kicked: {1}</color>", [Lang.BannedMessage] = "<color=#d9534f>{0} was BANNED: {1}</color>", [Lang.UnbannedMessage] = "Unbanned {0}", [Lang.BanNotFound] = "ID not found in ban list.", [Lang.StrippedInventory] = "Stripped inventory of {0}", [Lang.HealedPlayer] = "Healed {0}", [Lang.TeleportedTo] = "Teleported to {0}", [Lang.TeleportedHere] = "Teleported {0} to you", [Lang.UpMessage] = "Went up {0}m", [Lang.RepairedEntities] = "Repaired {0} entities in
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху