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

FREE SafeSpace : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 PenguinzTech <https://penguintech.io>
using System;
using Oxide.Core;
using Oxide.Core.Plugins;

namespace Oxide.Plugins
{
    [Info("SafeSpace", "PenguinzPlays", "1.0.0")]
    [Description("Kid-friendly server: blocks signs, global chat, voice, and notes unless player has permission")]
    class SafeSpace : RustPlugin
    {
        [PluginReference] Plugin GUIAnnouncements;

        private const string PermSigns      = "safespace.signs";
        private const string PermGlobalChat = "safespace.globalchat";
        private const string PermVoice      = "safespace.voice";
        private const string PermNotes      = "safespace.notes";

        private PluginConfig _config;

        #region Configuration

        private class PluginConfig
        {
            public bool BlockSigns      = true;
            public bool BlockGlobalChat = true;
            public bool BlockVoice      = true;
            public bool BlockNotes      = true;
        }

        protected override void LoadDefaultConfig()
        {
            _config = new PluginConfig();
            SaveConfig();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            _config = Config.ReadObject<PluginConfig>();
        }

        protected override void SaveConfig() => Config.WriteObject(_config);

        #endregion

        void Init()
        {
            permission.RegisterPermission(PermSigns, this);
            permission.RegisterPermission(PermGlobalChat, this);
            permission.RegisterPermission(PermVoice, this);
            permission.RegisterPermission(PermNotes, this);
        }

        void OnServerInitialized()
        {
            Puts($"SafeSpace active — Signs:{_config.BlockSigns} GlobalChat:{_config.BlockGlobalChat} Voice:{_config.BlockVoice} Notes:{_config.BlockNotes}");
        }

        // ─── Login announcement ─────────────────────────────────────────────
        // Voice is suppressed silently (spamming a message on every voice packet
        // is not viable), so we instead notify the player once on connect if
        // GUIAnnouncements is present. Falls back to ChatMessage if it isn't.
        void OnPlayerConnected(BasePlayer player)
        {
            if (!_config.BlockVoice) return;
            if (permission.UserHasPermission(player.UserIDString, PermVoice)) return;

            if (GUIAnnouncements != null)
                GUIAnnouncements.Call("CreateAnnouncement",
                    "Voice chat is disabled on this server.", "grey", "white", player);
            else
                player.ChatMessage("[SafeSpace] Voice chat is disabled on this server.");
        }

        // ─── Signs / photo frames ───────────────────────────────────────────
        // Fires when a player paints or applies an image to any Signage or
        // PhotoFrame entity. Return non-null to block the update.
        // Players can still place empty signs as building items.
        private object OnSignUpdate(BaseEntity sign, BasePlayer player,
            int textureIndex, byte[] stream, uint crc, string msg)
        {
            if (!_config.BlockSigns) return null;
            if (permission.UserHasPermission(player.UserIDString, PermSigns))
                return null;

            player.ChatMessage("[SafeSpace] Sign painting is disabled on this server.");
            return false;
        }

        // ─── Global chat ────────────────────────────────────────────────────
        // Fires before a chat message is broadcast. Only blocks Global channel;
        // Team, Local, Cards, and Clan channels are always allowed.
        private object OnPlayerChat(BasePlayer player, string message, int channel)
        {
            if (!_config.BlockGlobalChat) return null;
            if (channel != 0) return null; // 0 = Chat.ChatChannel.Global
            if (permission.UserHasPermission(player.UserIDString, PermGlobalChat))
                return null;

            player.ChatMessage("[SafeSpace] Global chat is disabled. Use team chat instead.");
            return false;
        }

        // ─── Voice chat ─────────────────────────────────────────────────────
        // Fires when voice data is received from a player. Return non-null to
        // suppress transmission. No chat message — would spam on every packet.
        private object OnPlayerVoice(BasePlayer player, Byte[] data)
        {
            if (!_config.BlockVoice) return null;
            if (permission.UserHasPermission(player.UserIDString, PermVoice))
                return null;

            return false;
        }

        // ─── Notes (workaround — no direct pre-hook exists) ─────────────────
        // Oxide has no pre-hook for note text editing (client-side UI). Instead
        // we clear item.text on item actions and loot-end events so anything
        // written by an unauthorized player is wiped before it can be shared.

        private void OnItemAction(Item item, string action, BasePlayer player)
        {
            if (!_config.BlockNotes) return;
            if (item?.info == null || player == null) return;
            if (item.info.shortname != "note") return;
            if (permission.UserHasPermission(player.UserIDString, PermNotes))
                return;

            if (!string.IsNullOrEmpty(item.text))
            {
                item.text = string.Empty;
                item.MarkDirty();
                player.ChatMessage("[SafeSpace] Notes are disabled on this server.");
            }
        }

        private void OnPlayerLootEnd(PlayerLoot loot)
        {
            if (!_config.BlockNotes) return;
            var player = loot?.GetComponent<BasePlayer>();
            if (player == null) return;
            if (permission.UserHasPermission(player.UserIDString, PermNotes))
                return;

            ClearNoteText(player);
        }

        // Also clear notes when a player picks up items containing text
        private void OnItemAddedToContainer(ItemContainer container, Item item)
        {
            if (!_config.BlockNotes) return;
            if (item?.info == null || item.info.shortname != "note") return;
            if (string.IsNullOrEmpty(item.text)) return;

            var player = container?.playerOwner;
            if (player == null) return;
            if (permission.UserHasPermission(player.UserIDString, PermNotes))
                return;

            item.text = string.Empty;
            item.MarkDirty();
        }

        private void ClearNoteText(BasePlayer player)
        {
            if (player.inventory?.containerMain == null) return;
            foreach (var item in player.inventory.containerMain.itemList)
            {
                if (item?.info == null) continue;
                if (item.info.shortname != "note") continue;
                if (string.IsNullOrEmpty(item.text)) continue;
                item.text = string.Empty;
                item.MarkDirty();
            }
            foreach (var item in player.inventory.containerBelt.itemList)
            {
                if (item?.info == null) continue;
                if (item.info.shortname != "note") continue;
                if (string.IsNullOrEmpty(item.text)) continue;
                item.text = string.Empty;
                item.MarkDirty();
            }
        }

        // ─── Status command ─────────────────────────────────────────────────
        [ChatCommand("safespace")]
        private void CmdSafeSpace(BasePlayer player, string command, string[] args)
        {
            var signs = !_config.BlockSigns || permission.UserHasPermission(player.UserIDString, PermSigns);
            var chat  = !_config.BlockGlobalChat || permission.UserHasPermission(player.UserIDString, PermGlobalChat);
            var voice = !_config.BlockVoice || permission.UserHasPermission(player.UserIDString, PermVoice);
            var notes = !_config.BlockNotes || permission.UserHasPermission(player.UserIDString, PermNotes);

            player.ChatMessage(
                "[SafeSpace] Your permissions:\n" +
                $"  Signs:       {(signs ? "allowed" : "blocked")}\n" +
                $"  Global chat: {(chat  ? "allowed" : "blocked")}\n" +
                $"  Voice chat:  {(voice ? "allowed" : "blocked")}\n" +
                $"  Notes:       {(notes ? "allowed" : "blocked")}");
        }
    }
}

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