Skip to main content
All notable changes to vrs_permanentid are documented here. The most recent release is at the top.
2026-08-08
Permanent IDs now belong to the player, not the character, and they finally show up where staff actually work: in admin commands and in txAdmin.
Upgrading from 1.0.0? The database migrates itself on first start. Back up first, see Installation.

⚠️ Breaking changes

  • One ID per account, not per character. IDs are now keyed on the player’s license instead of their citizenid. A player with three characters used to own three IDs; now they own one.
  • IDs now start at 1000 (Config.StartId), up from 1. This keeps them clear of live server IDs so both can be typed into the same commands without ambiguity. Only affects brand-new installs, existing IDs are never renumbered.
  • Server exports are online-only and never yield. GetPermanentIdByIdentifier and GetIdentifierByPermanentId used to fall back to a database lookup, which could crash the calling resource with “attempt to yield across C-call boundary”, an export cannot yield across a resource boundary. Query the vrs_permanent_ids table directly if you need offline lookups.
  • /id is now owned by this resource. QBox/QBCore register their own /id that prints the slot number; left alone, both fire on one chat message. The patch to disable theirs is in patches/.

Added

  • Automatic database migration from the 1.0.0 layout. Detects the old schema, keeps each player’s oldest ID, merges their other character rows into it, and moves the unique key from identifier to license. If the migration cannot complete, the resource refuses to assign any ID rather than risk handing every player the same row.
  • patches/, drop-in patches that teach admin commands the permanent ID without editing those commands one by one:
    • ox_lib, the playerId argument parser. One file, ~30 commands (/giveitem, /givemoney, /setjob, /revive, /givekeys, …).
    • qbx_core, qb-core, es_extended, the framework GetPlayer lookups, for commands that take the id as a plain number.
    • monitor, txAdmin (see below).
    • Every patch is statebag-based, so it carries no dependency on this resource, has no load-order requirement, and does nothing at all when vrs_permanentid is stopped.
  • txAdmin support, in three places:
    • permanent-ID lines in the live console, no patch needed;
    • the ID appended to the player name in the web panel and the in-game menu (monitor/resource/sv_playerlist.lua);
    • the ID in the panel’s sidebar badge in place of the slot number (monitor/panel/patch-panel.js). Display only, clicking a player, kicking, banning and spectating still use the real slot number.
  • Config.MinPid, the number below which a value is always read as a server ID. Published as the vrs_pid_min convar so the patches can read it without depending on this resource.
  • Config.Console, toggles the permanent-ID lines printed on connect, character load and disconnect.
  • GetPermanentIdByLicense(license) and GetIdentifierBySource(source) exports.
  • Installation guide, plain-language setup, and a rewritten patches/README.md.

Changed

  • IDs are assigned during playerConnecting instead of on character load. They have to exist before the player takes a slot, because txAdmin captures a player’s display name exactly once, at playerJoining, and never updates it afterwards. A character-keyed ID arrives far too late for that.
  • OnPlayerLoaded no longer assigns anything. It records which character is in play and publishes the character name.
  • The statebag is re-asserted on character load, since the client is not necessarily connected yet when playerJoining sets it.
  • /pid now works on any connected player, not only ones with a character loaded.
  • /findpid reports the account license instead of a citizenid.
  • Resource restart with players already online now re-adopts them.

Fixed

  • Duplicate entry '…' for key 'identifier' on character load after upgrading. CREATE TABLE IF NOT EXISTS cannot alter an existing table, so the 1.0.0 unique index on identifier survived the upgrade untouched. Made worse on a non-strict sql_mode, where MySQL silently accepted an empty identifier instead of raising an error, quietly creating junk rows. Now handled by the migration.
  • The temporary source used during playerConnecting is no longer written into the source-keyed lookup tables, it can differ from the ID the player ends up with, which left stale entries behind.
  • A failed migration no longer leaves connecting players waiting forever on an internal “ready” flag.

Notes for people who patch txAdmin

monitor is part of FXServer, not your server folder, so both txAdmin patches are erased by every artifacts update. Stock copies are saved alongside each patched file as .stock.bak.After re-applying the panel patch you must restart the txAdmin process itself, restarting the server is not enough, because txAdmin loads the whole panel into memory once at startup. Then hard-refresh your browser (Ctrl+Shift+R): the file keeps its name, so nothing else tells the browser it changed.
Initial release

Added

  • Permanent, per-character numeric IDs assigned on first login and stored in vrs_permanent_ids.
  • Zero-config install. Table auto-created, no SQL file required.
  • Framework auto-detection via vrs_bridge (QBox, QBCore, ESX).
  • Server-authoritative ID assignment via MySQL AUTO_INCREMENT.
  • Replicated statebags: Player(src).state.vrs_pid and Player(src).state.vrs_pid_name.
  • Commands: /id, /pid, /findpid, /showids. All renameable / disableable in config.lua.
  • Server exports: GetPermanentId, GetPermanentIdByIdentifier, GetIdentifierByPermanentId, GetSourceByPermanentId, GetAllOnline.
  • Client export: GetMyPermanentId.
  • ACE permission support (vrs.permanentid), with QBox/QBCore admin/god and ESX admin groups passing automatically.
  • Open locales/*.lua for translations with English fallback.
  • Escrow-open config.lua and locales/*.lua.
Last modified on August 8, 2026