Skip to content

API Reference

shmitzas edited this page Nov 12, 2026 · 2 revisions

API Reference

Every member of IVipCoreApiV1. Key: VIPCore.Api.v1. See API Integration for how to attach.

Every event is raised on the game thread.

A member newer than the server's VIPCore is a MissingMethodException at the call, not a build error. Contract 1.1.0 members need VIPCore 1.2.0+; contract 1.2.0 members, VIPCore 1.3.0+.


Readiness

Member Description
bool IsCoreReady() True once VIPCore has loaded
event Action? OnCoreReady Raised each time VIPCore finishes loading

Check IsCoreReady() before subscribing to OnCoreReady — a module loading after VIPCore would wait for an event that already fired.


Features

Member Description
void RegisterFeature(string featureKey, FeatureType featureType = FeatureType.Toggle, Action<IPlayer, FeatureState>? onSelectItem = null, Func<IPlayer, string>? displayNameResolver = null) Registers a feature. Registering a key again replaces it
void UnregisterFeature(string featureKey) Removes it
IEnumerable<string> GetAllRegisteredFeatures() Every registered key
void DescribeFeature(string featureKey, Func<IPlayer, string?> description) The line menus show under the feature's name. Null = no line. Contract 1.1.0
T? GetFeatureValue<T>(IPlayer player, string featureKey) where T : class, new() The feature's settings in the player's active group, bound to T
bool PlayerHasFeature(IPlayer player, string featureKey) Whether the player's group grants it
FeatureState GetPlayerFeatureState(IPlayer player, string featureKey) The player's state for it
void SetPlayerFeatureState(IPlayer player, string featureKey, FeatureState newState) Sets it. A Toggle's state is saved when the player leaves
void DisableAllFeatures() / EnableAllFeatures() Lock or unlock every registered feature's row in the menus. States, and so the features, don't change
public enum FeatureType { Toggle, Selectable, Hide }

public enum FeatureState
{
    Enabled = 0,
    Disabled = 1,    // the player switched it off
    NoAccess = 2     // the player's group doesn't grant it
}
Type In the menu
Toggle A row on Perks that switches it on or off. The state is saved with Cookies
Selectable A row on Perks that opens its choices on Customize. Without choices, it calls onSelectItem and shows the value saved under <key>.value
Hide No row. The feature still has a state
  • Without displayNameResolver, menus show the key.
  • onSelectItem runs when the player switches a Toggle, with the new state, or selects a Selectable without choices.
  • A feature's state is Enabled when the group grants it, unless the player switched it off, and NoAccess when it doesn't. States are set when the player's VIP loads.
  • PlayerHasFeature is true for Disabled too. Check GetPlayerFeatureState(...) == FeatureState.Enabled before applying a feature.
  • GetFeatureValue returns null for a player who isn't VIP or whose group lacks the key, and the defaults of T for a plain value such as 1. It reads the file as it is now, so it follows edits.

Choices

Member Description
void RegisterFeatureOptions(string featureKey, Func<IPlayer, IReadOnlyList<VipFeatureOption>> options, Func<IPlayer, string?> current, Action<IPlayer, string> choose) Lists a feature's choices on Customize. Contract 1.1.0
public sealed record VipFeatureOption(
    string Id, string Label,
    string? Group = null,        // sorts choices into sections
    string? Description = null,
    string? Color = null,        // a chat colour name such as "gold", or #rrggbb
    bool IsDefault = false);

current returns the Id in use, or null for the IsDefault one; choose applies a pick. The module saves the pick itself. DescribeFeature and RegisterFeatureOptions may run before RegisterFeature; they attach when it does.


Players and groups

Member Description
bool IsClientVip(IPlayer player) Holds a grant that hasn't expired, or an override
string GetClientVipGroup(IPlayer player) The active group, or ""
string[] GetClientVipGroups(IPlayer player) The groups the player's grants give. An override isn't listed
IReadOnlyList<VipGrant> GetClientVipGrants(IPlayer player) The player's grants, the active one first. Empty for a non-VIP. Contract 1.1.0
string[] GetVipGroups() Every configured group
int GetVipGroupWeight(string group) A group's Weight. 0 for an unknown group
IReadOnlyList<VipGroupInfo> GetGroupInfos() The configured groups, lightest first. Contract 1.1.0
VipFeatureView? GetFeatureView(IPlayer player, string featureKey) A feature as the player's menu shows it. Null when unregistered or Hide. Contract 1.1.0
public sealed record VipGrant(string Group, bool Global, long ExpiresAt, long GrantedAt)
{
    public bool Permanent => ExpiresAt == 0;
}

public sealed record VipGroupInfo(string Name, int Weight, int FeatureCount);

public sealed record VipFeatureView(
    string Key, FeatureType Type, string Name, string? Description,
    string? Value,               // a Selectable's current choice
    FeatureState State,
    bool Locked);                // can't be switched right now

Times are Unix seconds. GrantedAt is 0 for a grant made before VIPCore 1.2.0. FeatureCount counts the registered features the group grants.

A player's VIP is loaded when they join, so these answer only for connected players.


Granting

Member Description
void GiveClientVip(IPlayer player, string group, int time) Grants a group on this server. time in TimeMode units; 0 = permanent
void GiveClientVip(IPlayer player, string group, TimeSpan duration) The same, for an exact length whatever TimeMode is. Contract 1.2.0
void RemoveClientVip(IPlayer player) Removes the player's grants on this server. Global grants stay
void OverrideClientVipGroup(IPlayer player, string group) Makes group active, in memory only. A non-VIP becomes VIP
void ClearClientVipGroupOverride(IPlayer player) Ends the override and reloads the player's own grants
  • GiveClientVip and RemoveClientVip write to the database off the game thread, then raise PlayerLoaded or PlayerRemoved. A failed grant is logged as Failed to give temporary VIP to player ….
  • Time for a group the player already holds is added to what is left of it. A permanent grant is replaced instead, so it becomes timed.
  • OverrideClientVipGroup raises PlayerLoaded at once. The override ends when the player leaves; nothing is stored.

Cookies

Member Description
T GetPlayerCookie<T>(IPlayer player, string key) A value saved for the player, or default
void SetPlayerCookie<T>(IPlayer player, string key, T value) Saves a value for the player

Stored by Cookies, so every server on its database shares them. Without Cookies, reads return default and writes are dropped. VIPCore saves a feature's state under the feature's own key — use a key of your own, such as vip.fov.value.


Events

Event Signature
OnCoreReady Action
PlayerLoaded Action<IPlayer, string>
PlayerRemoved Action<IPlayer, string>
OnPlayerSpawn Action<IPlayer>
OnPlayerUseFeature Func<IPlayer, string, FeatureState, FeatureType, bool?>
Event Raised
PlayerLoaded When a VIP joins and whenever their grants change. The string is the active group
PlayerRemoved When a VIP leaves or loses their last group. The string is the group they had
OnPlayerSpawn When a human player joins, VIP or not, before their grants load. Not raised on respawns — hook EventPlayerSpawn for those
OnPlayerUseFeature Before a feature's onSelectItem runs. Return false to block it; null or true lets it through

Menus

Contract 1.1.0.

Member Description
void RegisterMenuPage(VipMenuPage page) Adds a page of your own to the VIP menu
void UnregisterMenuPage(string pageId) Removes it
bool OpenMenu(IPlayer player, string? pageId = null) Opens the VIP menu, or one of its pages with the menu as its parent. False when the player may see none of it
public sealed record VipMenuPage(
    string Id, int Order,
    Func<IPlayer, string> Label,
    Func<IPlayer, bool> IsAvailable,
    Func<IPlayer, IMenu> Build);

public static class VipMenuIds
{
    public const string Hub = "vipcore.hub";
    public const string Perks = "vipcore.perks";
    public const string Customize = "vipcore.customize";
    public const string Users = "vipcore.users";
    public const string UsersList = "vipcore.users.list";
    public const string Grant = "vipcore.grant";
    public const string GrantGroup = "vipcore.grant.group";      // Grant VIP's later steps; Requires VIPCore 1.4.0+
    public const string GrantLength = "vipcore.grant.length";
    public const string GrantScope = "vipcore.grant.scope";
}

Pages list after Customize, lowest Order first, then by id.

Rule Why
IsAvailable decides who sees the row A page that throws there is hidden, and logged
A Build that throws opens nothing It is logged as a warning naming the page
VIPCore's ids, and vipcore.users.list.*, are refused Logged as Menu page id '…' belongs to VIPCore; the page was not added.
Off the game thread, OpenMenu opens on the next tick Its answer is then a guess that doesn't ask pages' IsAvailable

Row tags

Every row of VIPCore's pages carries a record as its component Tag, so a custom renderer can draw it from data:

Record Row
VipFeatureRow(string FeatureKey) A perk on Perks
VipSectionRow(string FeatureKey, string? Group = null) The heading over a feature's choices, or one Group of them
VipOptionRow(string FeatureKey, VipFeatureOption Option, bool Selected) One choice
VipUserRow(VipUserInfo User, bool Selected) A VIP on VIP users
VipGrantRow(VipGrant Grant, bool Expanded) One of the selected VIP's grants
VipLengthRow(TimeSpan? Length, bool Selected, VipGrant? Extends = null) A length to grant on vipcore.grant.length, null = permanent; with Extends, a step that extends that grant
VipPlayerRow(ulong SteamId, string Name, string? Team, string? Group, bool Selected) A player to grant to, on Grant VIP's first page. Team is T, CT or SPEC
VipGroupRow(VipGroupInfo Group, bool Selected) A group to grant, on vipcore.grant.group
VipScopeRow(bool Global, bool Selected) Where a grant applies, on vipcore.grant.scope; selecting one grants it
VipActionRow(VipAction Action, VipGrant? Grant = null) An action, or a page's summary line
public enum VipAction { Search, Summary, Submit, MakePermanent, Remove, AddGroup, RemoveAll }

public sealed record VipUserInfo(ulong SteamId, string Name, long LastVisit, bool Online, IReadOnlyList<VipGrant> Grants);
public sealed record VipUserStats(int Users, int EndingThisWeek);                      // the admin pages' menu Tag
public sealed record VipFeatureLimit(int Left, int PerRound, DateTimeOffset? Until);   // a per-round page's menu Tag

A row whose state changes gets a new record, so a Tag never goes stale. A module page built the same way — sections, options, a VipActionRow summary and submit, a VipFeatureLimit — is drawn like VIPCore's own; VIP_GunMenu is one.


VipFeatureBase

An optional base class for a feature module.

public abstract class VipFeatureBase : IVipFeature
{
    public abstract string Feature { get; }    // the feature key

    protected VipFeatureBase(IVipCoreApiV1 api, ISwiftlyCore core);   // subscribes the three events below

    public virtual void OnPlayerSpawn(IPlayer player);    // on join, not on respawns
    public virtual void OnPlayerLoaded(IPlayer player, string group);
    public virtual void OnPlayerRemoved(IPlayer player, string group);
    public virtual void OnSelectItem(IPlayer player, FeatureState state);

    public void RegisterFeature(FeatureType featureType = FeatureType.Toggle, Func<IPlayer, string>? displayNameResolver = null);
    public void UnregisterFeature();           // also unsubscribes
}

Call RegisterFeature once VIPCore is ready, and UnregisterFeature from Unload.

Clone this wiki locally