codeAPI Reference

LimitsSystem Per-Player Spawn Limits

calendar_today May 3, 2026 schedule ~1 min read person patrickjr verified 50

LimitsSystem Per-Player Limits

Enforces configurable spawn limits per player with automatic tracking via ISpawnEvents.

CSHARP
using Sandbox.UI;

public sealed class LimitsSystem : GameObjectSystem<LimitsSystem>, Global.ISpawnEvents, IToolActionEvents
{
    [ConVar("sb.limit.props", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxPropsPerPlayer { get; set; } = -1;

    [ConVar("sb.limit.explosives", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxExplosivesPerPlayer { get; set; } = -1;

    [ConVar("sb.limit.balloons", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxBalloons { get; set; } = -1;

    [ConVar("sb.limit.constraints", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxConstraints { get; set; } = -1;

    [ConVar("sb.limit.emitters", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxEmitters { get; set; } = -1;

    [ConVar("sb.limit.thrusters", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxThrusters { get; set; } = -1;

    [ConVar("sb.limit.hoverballs", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxHoverballs { get; set; } = -1;

    [ConVar("sb.limit.wheels", ConVarFlags.Replicated | ConVarFlags.Server | ConVarFlags.GameSetting)]
    public static int MaxWheels { get; set; } = -1;

    private readonly Dictionary<long, List<GameObject>> _tracked = new();
    private readonly HashSet<GameObject> _allTracked = new();

    void Global.ISpawnEvents.OnSpawn(Global.ISpawnEvents.SpawnData e)
    {
        if (e.Player?.Connection is not { } conn) return;
        var steamId = conn.SteamId;

        if (IsExceeded(MaxPropsPerPlayer, Count(steamId)))
        {
            e.Cancelled = true;
            return;
        }
    }

    void Global.ISpawnEvents.OnPostSpawn(Global.ISpawnEvents.PostSpawnData e)
    {
        if (e.Player?.Connection is { } conn)
            Track(conn.SteamId, e.Objects);
    }

    private static bool IsExceeded(int limit, int count) => limit >= 0 && count >= limit;
}

Key Features

  • Per-player tracking via SteamId dictionary
  • ISpawnEvents integration for automatic counting
  • Cancellable spawns - Set e.Cancelled = true when limit exceeded
  • ConVar settings - Server-configurable limits
  • Available limits: props, explosives, balloons, constraints, emitters, thrusters, hoverballs, wheels
Was this helpful?