Skip to content
RustPluginGenerator

CanUseUI

CanUseUI is called whenever CUIHelper.AddUi sends a UI payload to a player, before the AddUI ClientRPC is sent. Returning a non-null value blocks that payload from reaching the client.

Signature
object CanUseUI(BasePlayer player, string json)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer whose client is about to receive the UI payload. Null-check it; a disconnected player still reaches the hook with a valid object but no connection.
jsonstringThe raw CUI JSON string that is being pushed to the client. It is the serialized CuiElementContainer, so inspect it with string checks (name, text, command) rather than parsing it.

Return value

Returning null lets AddUi send the AddUI ClientRPC and return true. Returning anything non-null (even false or an empty string) skips the RPC and makes the original AddUi return false, so the client never receives that payload.

How it works

The hook fires inside CUIHelper.AddUi(BasePlayer player, string json), the static helper that every CUI plugin uses to push an element container to a client. Whenever AddUi is invoked with a valid player and connection, Oxide calls CanUseUI first. Returning null lets the original code run and the AddUI ClientRPC is sent; any non-null return makes AddUi skip the RPC and return false to the caller.

Use player to scope decisions per player (permissions, admin state, combat, mounted state). Use json when you need to filter by content rather than by player; a simple json.Contains("MyPluginPanel") check is enough to target a specific element name, since CUI names appear verbatim in the serialized string.

Because the hook fires on every CUI push, it is hot: a plugin that redraws on tick or on damage will trigger it many times per second per player. Keep the logic cheap, never call Puts or PrintWarning here, and avoid parsing JSON. There is no more specific parameter type to narrow on: player is always a BasePlayer and json is always a string, so every call reaches every registered handler.

Example plugin: Block CUI for players in combat

CombatUiBlocker.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Combat UI Blocker", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks CUI payloads for players who recently entered combat.")]
    public class CombatUiBlocker : RustPlugin
    {
        private const string PermCheck = "combatuiblocker.check";

        private class PluginConfig
        {
            [JsonProperty("Combat window in seconds")]
            public float CombatWindow = 8f;
        }

        private PluginConfig config;
        private readonly Dictionary<ulong, float> combatUntil = new Dictionary<ulong, float>();

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

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

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Status"] = "Your UI block window is {0} seconds.",
                ["NoPerm"] = "You are not allowed to use this command."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
        {
            return string.Format(lang.GetMessage(key, this, userId), args);
        }

        private void Init()
        {
            permission.RegisterPermission(PermCheck, this);
        }

        private object CanUseUI(BasePlayer player, string json)
        {
            if (player == null) return null;

            float until;
            if (!combatUntil.TryGetValue(player.userID, out until)) return null;
            if (Time.realtimeSinceStartup >= until) return null;

            return false;
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (info == null) return;

            var victim = entity as BasePlayer;
            if (victim != null && !victim.IsNpc)
            {
                Mark(victim);
            }

            var attacker = info.InitiatorPlayer;
            if (attacker != null && !attacker.IsNpc)
            {
                Mark(attacker);
            }
        }

        private void Mark(BasePlayer player)
        {
            combatUntil[player.userID] = Time.realtimeSinceStartup + Mathf.Max(0f, config.CombatWindow);
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player != null) combatUntil.Remove(player.userID);
        }

        [ChatCommand("uiblock")]
        private void CmdUiBlock(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;

            if (!permission.UserHasPermission(player.UserIDString, PermCheck))
            {
                player.ChatMessage(Msg("NoPerm", player.UserIDString));
                return;
            }

            player.ChatMessage(Msg("Status", player.UserIDString, config.CombatWindow.ToString("0.#")));
        }

        private void Unload()
        {
            combatUntil.Clear();
        }
    }
}

The plugin refuses UI payloads for players who are in combat, so custom panels do not flash over the screen while fighting. A player is treated as in combat if they took or dealt damage recently; OnEntityTakeDamage stamps the attacker and victim into a dictionary with a timestamp taken from Time.realtimeSinceStartup. In CanUseUI we look up that stamp and return false when it is inside the configured window, which stops the payload from reaching the client. OnPlayerConnected clears stale state, Unload clears the dictionary, and a chat command lets permitted players check the current window. All player-facing text goes through lang.

Common use cases

  • Hide custom UI during raids or combat

    Suppress plugin panels while a player is in combat so scoreboards, shop windows and HUD popups do not cover the screen when timing matters.

  • Per-player UI gating by permission

    Block any payload for players who lack a permission, for example keeping a trader panel hidden from players who have not accepted a server rule.

  • Filter a specific panel by element name

    Inspect the json string for a known element name and block only that panel, leaving every other plugin's UI untouched.

Pitfalls

  • Blocking breaks the calling plugin

    AddUi returns false to its caller, but most plugins ignore that value and assume the UI is on screen. If you block a panel, that plugin may still think it is open and refuse to redraw it.

  • Fires on every UI push

    HUD plugins can push dozens of payloads per second per player. Keep the handler O(1) and never log inside it, or you will flood the server log and the console.

  • String checks can misfire

    The json argument is a serialized container, so searching for a short name or word can match unrelated elements. Use distinctive element names and prefer player-based gating when possible.

Build a plugin with CanUseUI

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Hide custom UI during raids or combat using the CanUseUI hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with CanUseUI

Generate