Inicio › Documentación › Personalización · origen_parking
La carpeta custom/ te permite integrar cualquier framework, sistema de llaves o sistema de combustible sin tocar el núcleo. Todos los ficheros de aquí sobreviven a las actualizaciones.
custom/
├── sv_framework.lua — server-side: identifier, permissions, money, notifications, garages
├── sv_keys.lua — server-side: give keys, set lock state
├── cl_framework.lua — client-side: identifier, notifications, player loaded event
├── cl_keys.lua — client-side: read lock state
└── cl_fuel.lua — client-side: get/set fuel levelFramework.GetIdentifier(source) → string | nilDevuelve el identificador único de un jugador (citizenid / license). Se llama en cada acción de aparcar o recuperar.
function Framework.GetIdentifier(source)
-- Config.Framework == 'custom'
return nil -- replace with your own logic
endFramework.GetVehicleOwner(plate) → string | nilDevuelve el identificador del propietario de una matrícula a partir de la tabla de vehículos del framework.
function Framework.GetVehicleOwner(plate)
-- Config.Framework == 'custom'
return nil
endFramework.SetVehicleStorageState(plate, stored)Marca un vehículo como guardado (stored = true) o fuera (stored = false) en la tabla de vehículos del framework.
function Framework.SetVehicleStorageState(plate, stored)
-- Config.Framework == 'custom'
endFramework.HasAdminPermission(source, permission) → booleanSe llama en todos los callbacks de administración. Los sistemas de permisos se comprueban en este orden:
origen_admin — exports['origen_admin']:HasPermission(src, permission)ace — IsPlayerAceAllowed(src, Config.AdminAceNode)qbx / qb — comprueba PlayerData.group para god, superadmin, adminesx — comprueba xPlayer.getGroup() para superadmin, admincustom — impleméntalo más abajofunction Framework.HasAdminPermission(source, permission)
-- Config.AdminSystem == 'custom'
return false
endFramework.Notify(source, message, ntype)Envía una notificación a un jugador. ntype: 'info' | 'success' | 'error'
function Framework.Notify(source, message, ntype)
-- Config.NotifySystem == 'custom'
endFramework.GetGarages() → table[]Devuelve una lista de garajes para el panel de administración. Cada entrada: { id, name, label }.
function Framework.GetGarages()
-- Config.GarageIntegration == 'custom'
return {}
endFramework.GetMoney(source) → numberDevuelve el saldo en efectivo de un jugador. Lo usa el sistema de coste de aparcamiento.
function Framework.GetMoney(source)
-- Config.Framework == 'custom'
return 0
endFramework.RemoveMoney(source, amount) → booleanDescuenta efectivo a un jugador. Devuelve true si lo consigue.
function Framework.RemoveMoney(source, amount)
-- Config.Framework == 'custom'
return false
endFramework.GetVehicleState(plate) → number | nilDevuelve el estado de almacenamiento de un vehículo según la tabla del framework (1 = fuera, 0 = guardado, o nil si no se encuentra).
function Framework.GetVehicleState(plate)
-- Config.Framework == 'custom'
return nil
endEl sistema de aparcamiento se comunica con tu sistema de llaves mediante dos ficheros puente: custom/sv_keys.lua (dar llaves y fijar el bloqueo) y custom/cl_keys.lua (leer el estado del bloqueo). El camino que se ejecuta depende de Config.KeySystem:
Config.KeySystem |
Comportamiento |
|---|---|
qbx_vehiclekeys |
GiveKeys + SetLockState mediante los exports de qbx, con respaldo nativo. |
qb-vehiclekeys |
GiveKeys mediante el export de qb, bloqueo aplicado con el nativo + state bag. |
qs-vehiclekeys |
GiveKeys + setLocked mediante los exports de qs, con respaldo nativo. |
rk-keys |
addKey mediante el export de rk, bloqueo nativo. |
none |
No se dan llaves, los vehículos aparecen desbloqueados. |
custom |
Implementas el puente en sv_keys.lua / cl_keys.lua. |
Sea cual sea Config.KeySystem, la forma recomendada de controlar el aparcar/desaparcar desde tu sistema de llaves son los hooks de cliente explícitos que verás a continuación. Son deterministas y ejecutan todas las comprobaciones de elegibilidad, sin adivinar nada.
Llama a estos exports de cliente desde tu sistema de llaves cada vez que el jugador bloquee o desbloquee un vehículo. El sistema de aparcamiento se encarga del resto (comprobaciones de elegibilidad, aparcar/desaparcar en el servidor). Ambos aceptan un handle de entidad del vehículo y no hacen nada si el vehículo no es elegible.
exports['origen_parking']:onVehicleLocked(vehicle) -- park this vehicle
exports['origen_parking']:onVehicleUnlocked(vehicle) -- unpark this vehicleConexión desde un evento de bloqueo/desbloqueo (la mayoría de los sistemas de llaves de qb / esx lanzan uno):
AddEventHandler('my_keys:client:vehicleLocked', function(veh)
exports['origen_parking']:onVehicleLocked(veh)
end)
AddEventHandler('my_keys:client:vehicleUnlocked', function(veh)
exports['origen_parking']:onVehicleUnlocked(veh)
end)Conexión desde el state bag del bloqueo de puertas (qbx_vehiclekeys y similares publican doorslockstate):
AddStateBagChangeHandler('doorslockstate', nil, function(bagName, _, value)
local veh = GetEntityFromStateBagName(bagName)
if veh == 0 then return end
if value and value >= 2 then
exports['origen_parking']:onVehicleLocked(veh)
else
exports['origen_parking']:onVehicleUnlocked(veh)
end
end)Los sistemas de llaves que solo usan nativos bloquean el coche en el servidor, así que el cliente propietario de la entidad no siempre puede observar el bloqueo mediante el sondeo nativo. Para esos sistemas, los hooks explícitos de arriba son el único disparador fiable: úsalos en lugar de Config.AutomaticParking.
Keys.GiveKeys(source, entity, plate)Da las llaves del vehículo a un jugador al aparecer. Solo se ejecuta cuando Config.GiveKeysOnSpawn = true. Cada rama comprueba que el recurso de llaves esté en started y envuelve el export en pcall, de modo que un sistema de llaves ausente nunca rompe la aparición.
| Parámetro | Tipo | Descripción |
|---|---|---|
source |
number |
ID de servidor del jugador que recibe las llaves. |
entity |
number |
Handle de entidad del vehículo (puede ser 0 si aún no ha aparecido: usa plate). |
plate |
string |
Matrícula del vehículo. |
Soportados de serie: qbx_vehiclekeys, qb-vehiclekeys, qs-vehiclekeys, rk-keys. Para custom, añade tu propia llamada al export:
function Keys.GiveKeys(source, entity, plate)
-- Config.KeySystem == 'custom'
-- exports['my_key_resource']:GiveKey(source, plate)
endKeys.SetLock(entity, locked)Bloquea o desbloquea una entidad de vehículo en el servidor. Solo se ejecuta cuando Config.LockVehiclesOnSpawn = true. locked = true → bloqueado (estado 2), false → desbloqueado (estado 1). Todas las ramas recurren al nativo + state bag para que los demás jugadores vean el vehículo aparcado como bloqueado.
| Parámetro | Tipo | Descripción |
|---|---|---|
entity |
number |
Handle de entidad del vehículo. |
locked |
boolean |
true para bloquear, false para desbloquear. |
function Keys.SetLock(entity, locked)
-- Config.KeySystem == 'custom' / 'none' / 'rk-keys' → native fallback:
SetVehicleDoorsLocked(entity, locked and 2 or 1)
Entity(entity).state.doorslockstate = locked and 2 or 1
endFramework.GetLocalIdentifier() → string | nilDevuelve, en el cliente, el identificador único del jugador local.
function Framework.GetLocalIdentifier()
-- Config.Framework == 'custom'
return nil
endFramework.NotifyClient(message, notifyType)Muestra una notificación al jugador local. notifyType: 'info' | 'success' | 'error'
function Framework.NotifyClient(message, notifyType)
-- Config.NotifySystem == 'custom'
endFramework.OnPlayerLoaded(callback)Registra un callback que se dispara cuando los datos del jugador están listos. Se usa para la sincronización inicial.
function Framework.OnPlayerLoaded(callback)
-- Config.Framework == 'custom'
CreateThread(function() Wait(0); callback() end)
endKeys.IsLocked(vehicle) → booleanDevuelve true si el vehículo está bloqueado en ese momento. Lo usa únicamente el sondeo opcional de aparcamiento automático (Config.AutomaticParking) para detectar cuándo el jugador bloquea su coche después de bajarse. Comprueba tanto el estado de bloqueo nativo como el state bag doorslockstate, sin salir nunca antes por un state bag desbloqueado, para que un bag obsoleto no oculte un bloqueo nativo real.
| Parámetro | Tipo | Descripción |
|---|---|---|
vehicle |
number |
Handle de entidad del vehículo. |
function Keys.IsLocked(vehicle)
-- Native lock: 0=None 1=Unlocked 2=Locked 3=LockedForPlayer 4=StuckForPlayer
if GetVehicleDoorLockStatus(vehicle) >= 2 then return true end
local stateBagLock = Entity(vehicle).state.doorslockstate
if stateBagLock ~= nil and stateBagLock >= 2 then return true end
return false
endSi la detección automática no es fiable con tu sistema de llaves, prescinde del sondeo y usa los hooks explícitos (onVehicleLocked / onVehicleUnlocked) documentados arriba en Integración del sistema de llaves.
Fuel.Get(vehicle) → numberDevuelve el nivel de combustible actual (0–100) de un vehículo.
Orden de autodetección: ox_fuel → LegacyFuel → ps-fuel → cdn-fuel → native.
function Fuel.Get(vehicle)
-- Config.FuelSystem == 'custom'
return GetVehicleFuelLevel(vehicle)
endFuel.Set(vehicle, level)Establece el nivel de combustible (0–100) de un vehículo. Llama siempre a SetVehicleFuelLevel como base y después al sistema activo por encima.
function Fuel.Set(vehicle, level)
-- Config.FuelSystem == 'custom'
SetVehicleFuelLevel(vehicle, level + 0.0)
end