RivalityFX Docsrivalityfx.com ↗

Registration — registerPack / unregisterPack

Stability: Stable.

The entry point for every cosmetic pack. A pack resource builds a plain-data pack descriptor and registers it with the SDK. customization mirrors the registry to render the "Appearance" page and apply skins — it is a consumer, so a pack depends on both sdk (this contract) and customization (the runtime).

Registration runs as a shared script: the descriptor lands in the SDK's client registry (where the cosmetic is rendered and applied) and its server registry (the equip-gating authority — ownership is checked server-side before an equip is granted). Preferences stay client KVP; no database. This is the cosmetic sibling of registerMode — the same registry pattern, a different domain.

exports.sdk:registerPack(def)

Registers a pack. Call it from a script listed in your pack's shared_scripts once the SDK has started — the shipped templates use the SDK helper, which registers now AND re-announces on a live restart sdk:

Sdk.autoRegister(function() exports.sdk:registerPack(PACK) end)
ParameterTypeRequiredNotes
deftableyesThe pack descriptor. Must have a unique def.id.

Validation

The descriptor is validated before it is accepted (Sdk.validatePack). A plain-data pack otherwise fails silently — a skin card that does nothing, a missing tab. Validation turns those into a clear console diagnostic.

  • Errors refuse the pack. If anything is structurally wrong, the pack is not registered and every problem is printed:

    [sdk] pack neon REFUSED -- 1 error(s):
    [sdk]   - `skins` must be a non-empty array of items
  • Warnings are logged but allowed (e.g. an unknown apiVersion, a missing label, an unknown rarity).

  • What's checked: id, the apiVersion pin, the kind/status/access enums, a non-empty skins array where each item has an id (and, advised, a label/rarity) — plus, for kind='outfit', the clothing payload (base/collection/pieces — see the outfit validation rules). Asset existence is NOT checked here — a skin's model (IsModelInCdimage) and an outfit's mounted collection are verified client-side at apply time (in customization), because a streamed asset may not be indexed/mounted yet at registration.

Behaviour

  • The SDK tags the descriptor with the calling resource (def.resource = GetInvokingResource()), so it can drop the pack if that resource stops.

  • Missing fields are filled with defaults at registration time:

    FieldDefault applied
    kind'skin'
    status'owned'
    access'player'
    skins{}
  • Registering an id that already exists overwrites the previous descriptor.

  • On success the SDK announces sdk:packRegistered(id) (so customization mirrors it) and prints:

    [sdk] pack registered: <id> (<name>) from <resource>

exports.sdk:unregisterPack(id)

Removes a pack by id. After this, customization drops it from the catalogue (it listens for sdk:packUnregistered).

exports.sdk:unregisterPack('neon')
ParameterTypeRequiredNotes
idstringyesThe id of a registered pack. Unknown ids are a no-op.

Automatic cleanup

You usually don't need unregisterPack. When a pack's owning resource stops, the SDK automatically unregisters every pack tagged with that resource and fires sdk:packUnregistered, so customization drops its skins from the catalogue.

Versioning

The cosmetic contract has its own version, exports.sdk:packApiVersion(), independent of the mode contract (exports.sdk:modeApiVersion()). Pin apiVersion = N in your pack so a future SDK can flag a breaking change.

See also