Skip to content
RustPluginGenerator

OnFireworkDesignChange

OnFireworkDesignChange is called on the server when a player submits a new star pattern for a PatternFirework entity, before the design is validated and applied. Returning a non-null value cancels the change.

Signature
object OnFireworkDesignChange(PatternFirework patternFirework, ProtoBuf.PatternFirework.Design design, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
patternFireworkPatternFireworkThe PatternFirework entity whose design is being changed. Use it to read its position, owner (OwnerID) or net identity when validating the change.
designProtoBuf.PatternFirework.DesignThe ProtoBuf.PatternFirework.Design sent by the client, containing the star layout. It can be null, so check design?.stars before reading anything from it.
playerBasePlayerThe BasePlayer who submitted the new design over RPC. The game already verified PlayerCanModify before this hook runs, so the player is non-null on the server.

Return value

Returning null lets the game validate and apply the submitted design normally. Returning any non-null value (even false) makes ServerSetFireworkDesign return immediately, so the new pattern is not applied to the firework.

How it works

The hook fires inside PatternFirework.ServerSetFireworkDesign, right after the server reads the design protobuf from the client RPC and confirms the sender passes PlayerCanModify. That means it runs for every accepted design submission: a player editing stars in the pattern editor and confirming the layout. Because it fires before the star list is checked, design and design.stars are untrusted input — treat them as client data.

The parameters give you the entity, the submitted design and the requesting player. You can use them to enforce your own size limits on design.stars, block edits while a cooldown is active, or log who changed which firework. The original method returns void, so the hook only decides whether the game continues. The player and firework are reliable, but design can be null when the RPC payload is malformed.

Declaring player as BasePlayer is the exact type the game passes, so you cannot narrow it further. This hook has only this one signature and one call site.

Example plugin: Cap star count and log firework design edits

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

namespace Oxide.Plugins
{
    [Info("Firework Design Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Limits the number of stars in pattern firework designs and logs submitted edits.")]
    public class FireworkDesignGuard : RustPlugin
    {
        private const string PermUse = "fireworkdesignguard.use";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Maximum stars per design")]
            public int MaxStars { get; set; } = 40;

            [JsonProperty("Log accepted design edits to console")]
            public bool LogAccepted { get; set; } = true;
        }

        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>
            {
                ["TooManyStars"] = "This design has {0} stars, the limit is {1}.",
                ["NoPermission"] = "You are not allowed to program pattern fireworks."
            }, this);
        }

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

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

        private object OnFireworkDesignChange(PatternFirework patternFirework, ProtoBuf.PatternFirework.Design design, BasePlayer player)
        {
            if (player == null || patternFirework == null) return null;
            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return false;
            }

            int starCount = design?.stars != null ? design.stars.Count : 0;
            if (starCount > config.MaxStars)
            {
                player.ChatMessage(Msg("TooManyStars", player.UserIDString, starCount, config.MaxStars));
                return false;
            }

            if (config.LogAccepted)
            {
                Puts($"{player.displayName} ({player.UserIDString}) set a design with {starCount} stars on firework {patternFirework.net.ID.Value}");
            }

            return null;
        }
    }
}

The plugin reads a configurable maximum star count from oxide/config/FireworkDesignGuard.json. In OnFireworkDesignChange it null-checks the design and its stars list, then counts the entries and rejects the submission when the count exceeds the limit, sending a localized chat message to the player and returning false to cancel. Accepted edits are logged to the server console with the player name, the firework entity ID and the star count. Startup registers the permission helper only for future extension; the core limit is config-driven so admins can tune it without recompiling.

Common use cases

  • Enforce maximum star count

    Reject designs with more stars than your server allows to keep pattern fireworks cheap to render and store.

  • Audit edits

    Log the player, entity ID and star count of every submitted design so you can trace griefing or abuse of the pattern editor.

  • Restrict editing by permission

    Return a non-null value for players without a specific permission so only approved users can reprogram fireworks on your server.

Pitfalls

  • Design can be null

    A malformed RPC may deliver a null design or null stars. Accessing them without checks throws inside the hook and the change is skipped anyway.

  • Returning false still cancels

    The game stops the method whenever the hook returns anything other than null, so return false; blocks the design just like return true;.

  • PlayerCanModify runs first

    The hook only fires after the game already verified the player may modify the firework, so it cannot be used to allow edits the game itself rejects.

Build a plugin with OnFireworkDesignChange

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

Prompt: Enforce maximum star count using the OnFireworkDesignChange 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 OnFireworkDesignChange

Generate