Skip to content
RustPluginGenerator

OnSolarPanelSunUpdate

OnSolarPanelSunUpdate is called whenever a SolarPanel recalculates its power output from the current sun angle, right before the new value is applied to the grid.

Signature
object OnSolarPanelSunUpdate(SolarPanel solarPanel, int amount)

Parameters

Hook parameters
ParameterTypeDescription
solarPanelSolarPanelThe SolarPanel entity whose output was just recalculated. Use it to read its position, rotation, health fraction, or to compare against other panels.
amountintThe newly computed power output in watts for this update, already scaled by panel health and sun angle. This is the value the panel will store and push into the power grid.

Return value

Returning null lets the game continue and call MarkDirty() so the new output is networked to clients. Returning any non-null value stops that branch, so the panel keeps its new currentEnergy internally but is not marked dirty and clients are not sent the update.

How it works

The hook fires inside SolarPanel.SunUpdate, the routine a deployed panel runs to convert the current sun position into watts. The game first computes the raw output, multiplies it by the panel's healthFraction, and converts the result to an integer; only if that integer differs from the panel's previous output does it call OnSolarPanelSunUpdate with the panel and the new wattage. Because the call is gated on a changed value, it does not fire on every tick for a panel producing a steady output.

Both parameters are useful: solarPanel gives you the entity (net.ID, transform.position, Health(), net), and amount is the exact figure the panel is about to publish. Declaring the first parameter as a more specific type is not useful here because the argument is always a SolarPanel; declaring it as a broader type such as BaseEntity would simply match the same calls. Since the hook runs during the panel's own update, keep any work inside it cheap.

Example plugin: Cap solar panel output during a server event

SolarOutputCap.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Solar Output Cap", "RustPluginGenerator", "1.0.0")]
    [Description("Limits the maximum power output of solar panels by applying a health penalty when the cap is exceeded")]
    public class SolarOutputCap : RustPlugin
    {
        private const string PermToggle = "solaroutputcap.toggle";

        private class PluginConfig
        {
            [JsonProperty("Maximum output in watts")]
            public int MaxWatts = 50;

            [JsonProperty("Health penalty per blocked update")]
            public float HealthPenalty = 1f;
        }

        private PluginConfig config;

        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>
            {
                ["CapInfo"] = "Solar cap is currently {0}. Maximum output: {1} W.",
                ["CapChanged"] = "Solar cap is now {0}.",
                ["NoPermission"] = "You do not have permission to use this command."
            }, 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(PermToggle, this);
        }

        [ChatCommand("solarcap")]
        private void CmdSolarCap(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermToggle))
            {
                SendReply(player, Msg("NoPermission", player.UserIDString));
                return;
            }

            if (args.Length == 0)
            {
                SendReply(player, Msg("CapInfo", player.UserIDString, config.MaxWatts > 0 ? "enabled" : "disabled", config.MaxWatts));
                return;
            }

            int watts;
            if (int.TryParse(args[0], out watts) && watts >= 0)
            {
                config.MaxWatts = watts;
                SaveConfig();
                SendReply(player, Msg("CapChanged", player.UserIDString, watts));
            }
        }

        private object OnSolarPanelSunUpdate(SolarPanel solarPanel, int amount)
        {
            if (solarPanel == null || config.MaxWatts <= 0) return null;
            if (amount <= config.MaxWatts) return null;

            if (config.HealthPenalty > 0f)
            {
                solarPanel.Hurt(config.HealthPenalty);
            }

            // Suppress the network update for this blocked change.
            return true;
        }
    }
}

The plugin limits how much power any solar panel can produce, which is useful for balancing large solar farms. It reads a cap from the config and, in OnSolarPanelSunUpdate, checks the computed amount against it. When the panel would exceed the cap, the hook applies the penalty by scaling the panel's health down slightly with Hurt, so the next SunUpdate multiplies by a lower health fraction, and finally returns a non-null value to suppress the dirty mark. A command lets admins toggle the cap at runtime, with permission checks and localized reply messages.

Common use cases

  • Balance large solar farms

    Clamp or scale output so stacked panels cannot supply unlimited power, helping keep raid and base economy balanced on populated servers.

  • Event-based brownouts

    Temporarily throttle all panels during a scripted event by checking the current output and reacting when it changes.

  • Diagnostics and statistics

    Record output per panel ID over time to inspect which bases build the biggest power arrays, without changing the value.

Pitfalls

  • The hook is not called on every sun tick

    It only fires when the integer output differs from the previous value, so you cannot rely on it as a periodic timer for unchanged panels.

  • Returning a value skips the network update

    Any non-null return suppresses MarkDirty(). Clients then keep showing the old output until something else dirties the entity, so only block it deliberately.

  • The panel update runs often

    Avoid Puts, logging, or heavy per-player loops inside the hook; use a timer or a flag when you need to report something.

Build a plugin with OnSolarPanelSunUpdate

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

Prompt: Balance large solar farms using the OnSolarPanelSunUpdate 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 OnSolarPanelSunUpdate

Generate