v1.14.2

Features

  • Offline player delete character and jail option

Bug Fixes

  • Fixed incorrect self-referential export calls in giveVehicleKeys.
  • Added cleanup queries to remove stale luxu_admin_jail records for deleted offline players (ESX and QB frameworks).
  • Applied patches for voice.
  • Removed legacy cloudflare CLI, it's now auto in api.json
  • Improvements on different timezones

File Changes

⚙️ Configuration & Bridge Files

These files are not encrypted. Review the changes below — you may need to manually apply updates to your server's config files.

bridge/server/player.lua

  ---@param source number
  function player.revive(source)
-    TriggerClientEvent('visn_are:resetHealthBuffer', source)
-
      if GetResourceState('wasabi_ambulance_v2') == "started" then
          exports['wasabi_ambulance_v2']:RevivePlayer(source)
      elseif GetResourceState('wasabi_ambulance') == "started" then
          exports['wasabi_ambulance']:RevivePlayer(source)
      elseif GetResourceState('refine-hp') == "started" then
      end

      TriggerClientEvent('refine-hp:client:Revive', source)
      TriggerClientEvent('refine-hp:client:adminHeal', source)
+    TriggerClientEvent('visn_are:resetHealthBuffer', source)
  end

  ---@param source number
  function player.giveVehicleKeys(source, plate, modelHash)
              elseif resource.type == "client" then
                  return TriggerClientEvent(resource.event, table.unpack(resource.args))
              elseif resource.type == "export" then
-                return exports[resource.name][resource.event](exports[resource.name][resource.event], table.unpack(resource.args))
+                return exports[resource.name][resource.event](table.unpack(resource.args))
              end
          end
      end

  function player.getGender(playerObj)
  end

  function player.openClothingMenu(source)
-    if GetResourceState('illenium-appearance') == "started" then
+    if GetResourceState("17mov_CharacterSystem") == "started" then
+        TriggerClientEvent("17mov_CharacterSystem:OpenOutfitsMenu", source)
+    elseif GetResourceState('illenium-appearance') == "started" then
          TriggerClientEvent("illenium-appearance:client:openClothingShop", source, true)
      elseif GetResourceState('qb-clothing') == "started" then
          TriggerClientEvent('qb-clothing:client:openMenu', source)

config/config.json

    "advanced_configuration": {
-    "disable_map": false
+    "disable_map": false,
+    "disable_coords_history": true
    }
  }

config/database/queries.d.ts

   getOfflinePlayer(charId: string): Promise<OfflinePlayer | null>;

+  /**
+   * Returns the last saved world position for an offline character.
+   * Used by admin jail so the player can be returned after the sentence ends.
+   */
+  getOfflinePlayerLastCoords(charId: string): Promise<{ x: number; y: number; z: number } | null>;
+
   /**
    * Searches offline players by a search term (minimum 2 characters).
    * Override this to customise the search behaviour for your database schema.

config/database/queries.js

    /**
     * Returns the last saved world position for an offline character.
     * Used by admin jail so the player can be returned after the sentence ends.
     * @param {string} charId
     * @returns {Promise<{ x: number, y: number, z: number } | null>}
     */
    async getOfflinePlayerLastCoords(charId) {
      let rawPosition = null;

      if (Framework.name === 'esx') {
        rawPosition = await oxmysql.scalar('SELECT position FROM users WHERE identifier = ?', [charId]);
      } else if (Framework.name === 'qb' || Framework.name === 'qbx') {
        rawPosition = await oxmysql.scalar('SELECT position FROM players WHERE citizenid = ?', [charId]);
      }

      if (!rawPosition) return null;

      try {
        const position = typeof rawPosition === 'string' ? JSON.parse(rawPosition) : rawPosition;
        const x = Number(position.x ?? position[0]);
        const y = Number(position.y ?? position[1]);
        const z = Number(position.z ?? position[2]);
        if ([x, y, z].some((value) => !Number.isFinite(value))) return null;
        return { x, y, z };
      } catch {
        return null;
      }
    },

    /**
     * Searches offline players by a search term (minimum 2 characters).
     *
     * ... (truncated for brevity) see full file for search impl ...
     */

      const queries = [];

      if (Framework.name === 'esx') {
+      queries.push({ query: 'DELETE FROM luxu_admin_jail WHERE char_id = ?', values: [charId] });

        // Add extra ESX cleanup queries before the main delete:
        queries.push({ query: 'DELETE FROM owned_vehicles WHERE owner = ?', values: [charId] });

        queries.push({ query: 'DELETE FROM users WHERE identifier = ?', values: [charId] });
      } else if (Framework.name === 'qb' || Framework.name === 'qbx') {
+      queries.push({ query: 'DELETE FROM luxu_admin_jail WHERE char_id = ?', values: [charId] });

        // Add extra QB/QBX cleanup queries before the main delete:
        queries.push({ query: 'DELETE FROM player_vehicles WHERE citizenid = ?', values: [charId] });

fxmanifest.lua

  author 'luxu-gg'
  description 'Admin menu for FiveM'
-version '1.14.1'
+version '1.14.2'

  dependencies {
      'oxmysql',
+    '/server:28009'
  }

  server_script "@oxmysql/lib/MySQL.lua"

sql/install.sql

 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

 ... similar updates applied to all other tables (group_members, blips, chats, media, player_notes, props, jail, zones, chat_messages, warnings, duty_sessions, staff_logs, player_coords_history, etc.)

 All CREATE TABLE statements now include consistent `ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`

Full list of files changed

Change File
Modified bridge/server/player.lua
Modified client/modules/actions.lua
Modified client/modules/nui.lua
Modified config/config.json
Modified config/database/queries.d.ts
Modified config/database/queries.js
Modified fxmanifest.lua
Modified server/vendor/mc.cjs
Modified server/index.js
Modified sql/install.sql
Modified web/