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_jailrecords 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/ |