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.
object OnFireworkDesignChange(PatternFirework patternFirework, ProtoBuf.PatternFirework.Design design, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
patternFirework | PatternFirework | The PatternFirework entity whose design is being changed. Use it to read its position, owner (OwnerID) or net identity when validating the change. |
design | ProtoBuf.PatternFirework.Design | The ProtoBuf.PatternFirework.Design sent by the client, containing the star layout. It can be null, so check design?.stars before reading anything from it. |
player | BasePlayer | The 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
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
designor nullstars. 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 likereturn 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.
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