Repository navigation
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+.
| 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.
| 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. -
onSelectItemruns when the player switches aToggle, with the new state, or selects aSelectablewithout choices. - A feature's state is
Enabledwhen the group grants it, unless the player switched it off, andNoAccesswhen it doesn't. States are set when the player's VIP loads. -
PlayerHasFeatureis true forDisabledtoo. CheckGetPlayerFeatureState(...) == FeatureState.Enabledbefore applying a feature. -
GetFeatureValuereturns null for a player who isn't VIP or whose group lacks the key, and the defaults ofTfor a plain value such as1. It reads the file as it is now, so it follows edits.
| 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.
| 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 nowTimes 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.
| 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 |
-
GiveClientVipandRemoveClientVipwrite to the database off the game thread, then raisePlayerLoadedorPlayerRemoved. A failed grant is logged asFailed 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.
-
OverrideClientVipGroupraisesPlayerLoadedat once. The override ends when the player leaves; nothing is stored.
| 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.
| 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 |
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
|
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 TagA 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.
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.