Inicio › Documentación › Personalización · origen_graffiti
La carpeta custom/ te permite ampliar origen_graffiti sin tocar el núcleo. Todos los ficheros de aquí son escrow_ignore: sobreviven a las actualizaciones.
custom/
├── client/
│ ├── hooks.lua — client-side event hooks
│ └── permissions.lua — client-side permission checks (UX feedback)
└── server/
├── hooks.lua — server-side event hooks
└── permissions.lua — server-side permission checks (authoritative)custom/client/hooks.luaEl núcleo los lanza en el lado del cliente. Añade tu lógica dentro de cada handler.
graffiti:hook:onTagAddedSe lanza cuando el cliente recibe un tag nuevo para renderizar, ya sea al guardar o por sincronización de zona.
AddEventHandler('graffiti:hook:onTagAdded', function(row)
-- row.id — DB tag ID
-- row.coords — vector3 center
-- row.created_by — license identifier
-- row.image_url — public image URL
-- row.created_at — UTC timestamp string
end)graffiti:hook:onTagRemovedSe lanza cuando el cliente elimina un tag del mundo local.
AddEventHandler('graffiti:hook:onTagRemoved', function(id, coords)
-- id — tag DB ID
-- coords — vector3 where the tag was
end)graffiti:hook:onCanvasModeChangedSe lanza cuando el jugador local entra o sale del modo lienzo (sesión de pintura activa). Útil para ocultar o mostrar el HUD, menús radiales, etc.
AddEventHandler('graffiti:hook:onCanvasModeChanged', function(active, context)
-- active — boolean (true = enter canvas, false = exit canvas)
-- context.state — current state string
-- context.sessionId
-- context.isOwner — boolean
end)custom/server/hooks.luaEl núcleo los lanza en el lado del servidor. Añade tu lógica dentro de cada handler.
graffiti:hook:onTagCreatedSe lanza cuando un jugador guarda un grafiti correctamente.
AddEventHandler('graffiti:hook:onTagCreated', function(src, data)
-- src — server ID of the player
-- data.id — DB tag ID
-- data.coords — vector3 center
-- data.created_by — license identifier
-- data.image_url — public image URL (Fivemanage)
-- data.created_at — UTC timestamp string
end)Ejemplo — registrar la creación de grafitis:
AddEventHandler('graffiti:hook:onTagCreated', function(src, data)
print(('[graffiti] Player %s painted tag #%d at %s'):format(
data.created_by, data.id, tostring(data.coords)
))
end)graffiti:hook:onTagDeletedSe lanza cuando se elimina un tag, ya sea por un administrador o por un jugador con un borrador.
AddEventHandler('graffiti:hook:onTagDeleted', function(src, id, coords)
-- src — server ID of the player
-- id — deleted tag DB ID
-- coords — vector3 where the tag was
end)custom/client/permissions.luaEl núcleo los llama antes de cada acción para dar respuesta inmediata al usuario. Si devuelven false, la acción se cancela en el cliente.
Las comprobaciones del cliente son solo para la experiencia de usuario: se pueden saltar. Los permisos del servidor son siempre la barrera definitiva.
GraffitiPerms.canPaint(coords) → booleanSe llama al inicio de activateGraffiti(), antes de cualquier operación asíncrona.
function GraffitiPerms.canPaint(coords)
-- coords — vector3 player position when activating the spray
return true
endGraffitiPerms.canErase(coords) → booleanSe llama justo antes de entrar en el modo de borrado, una vez identificado el tag objetivo.
function GraffitiPerms.canErase(coords)
-- coords — vector3 center of the tag to erase
return true
endGraffitiPerms.canShop(coords) → booleanSe llama cuando el jugador pulsa E cerca de un punto de tienda, antes de abrir la NUI.
function GraffitiPerms.canShop(coords)
-- coords — vector3 shop location coordinates
return true
endcustom/server/permissions.luaComprobaciones definitivas que se hacen en el servidor antes de cada acción. Estas sí bloquean la operación.
GraffitiPerms.isAdmin(src) → booleanSe llama en todos los callbacks y comandos de administración. Valida contra Config.AdminGroups con tres capas de respaldo:
IsPlayerAceAllowed (QBCore, QBX, cualquier framework basado en ace)xPlayer.getGroup()Framework.GetIsFrameworkAdminfunction GraffitiPerms.isAdmin(src)
-- src — server ID
return true -- or your custom check
endGraffitiPerms.canPaint(src, coords) → booleanSe llama en graffiti:server:startSession después de validar la distancia.
function GraffitiPerms.canPaint(src, coords)
-- src — server ID
-- coords — vector3 canvas center
return true
endGraffitiPerms.canErase(src, coords) → booleanSe llama en graffiti:server:deleteWorldTag después de leer las coordenadas de la base de datos.
function GraffitiPerms.canErase(src, coords)
-- src — server ID
-- coords — vector3 tag coordinates
return true
endGraffitiPerms.canShop(src, coords) → booleanSe llama en graffiti:server:shopBuy antes de comprobar los fondos del jugador.
function GraffitiPerms.canShop(src, coords)
-- src — server ID
-- coords — vector3 player position at purchase time (may be nil)
return true
end