Hooks del servidor
Los hooks de ciclo de vida están en server/handlers.lua y se llaman Handlers.On…. Se ejecutan después de que algo haya pasado y no pueden deshacerlo; lo que devuelvan se ignora. Toda tabla data trae además hook, timestamp, schemaVersion y resource (detalles).
Resumen
Sección titulada «Resumen»| Área | Hooks |
|---|---|
| Ventas y subastas | OnSaleCompleted, OnAuctionEnded, OnReverseOfferAccepted |
| Anuncios | OnListingCreated, OnListingExpired, OnListingCancelled, OnListingBumped |
| Pujas | OnBidPlaced, OnProxyBidSet |
| Repartidor NPC | OnDeliveryCompleted, OnDeliveryFailed, OnDeliveryRobbed |
| Intercambios en persona y trueque | OnInPersonTradeCompleted, OnInPersonTradeCancelled, OnMeetupStatusChanged, OnBarterProposalCreated, OnBarterProposalStatusChanged |
| Reembolsos | OnRefundRequested, OnRefundApproved, OnRefundRejected |
| Social | OnPlayerRated, OnMessageSent, OnFavoriteChanged, OnFollowChanged, OnWishlistChanged, OnReportCreated |
| Perfil y buzón | OnProfileCreated, OnProfileUpdated, OnMailboxClaimed |
| Administración | OnAdminAction |
| Callbacks de config.lua | Config.Notify, Config.OnDeliveryRobbed |
Ventas y subastas
Sección titulada «Ventas y subastas»OnSaleCompleted
Sección titulada «OnSaleCompleted»Cuándo: un comprador paga un anuncio de precio fijo, un lote o una subasta holandesa, o usa Buy Now en una subasta. Se dispara en cuanto el pago queda registrado.
Lo que pasa después depende del modo de entrega, que te indican data.deliveryMode y data.stage:
deliveryMode |
stage |
settlementPending |
Qué pasa después |
|---|---|---|---|
'mailbox' |
'settled' |
false |
El objeto ya está en el inventario del comprador (o en su buzón del marketplace si no le cabía). No se dispara nada más |
'meetup' |
'settled' |
false |
El objeto espera en el buzón del comprador para recogerlo en el punto de recogida. No se dispara nada más |
'npc' |
'committed' |
true |
Sale una furgoneta de reparto. Más tarde se dispara OnDeliveryCompleted, OnDeliveryFailed u OnDeliveryRobbed |
'person' |
'committed' |
true |
Se crea un intercambio en persona (el vendedor tiene que estar conectado o la compra se rechaza). Más tarde se dispara OnInPersonTradeCompleted u OnInPersonTradeCancelled |
| Campo | Significado |
|---|---|
buyerSource, buyerId, buyerName |
El comprador |
sellerSource, sellerId, sellerName |
El vendedor (sellerSource es nil si está desconectado) |
item, itemLabel, itemMetadata, quantity |
Lo vendido |
category, rarity |
Categoría y rareza |
basePrice |
Precio del anuncio pagado (con descuentos), sin extras |
grossPaid |
Total pagado por el comprador |
platformFee, deliveryFee, modeSurcharge, npcDeliveryFee, insuranceFee |
Comisiones y extras (campos de dinero) |
sellerPayout |
Lo que recibe el vendedor |
price |
Alias antiguo de basePrice |
deliveryMode |
'mailbox', 'meetup', 'npc' o 'person' |
listingType |
'fixed', 'auction' (Buy Now), 'dutch' o 'bundle' |
stage, settlementPending |
Ver la tabla de arriba |
listingId |
ID del anuncio |
Ejemplo: XP para el vendedor cuando la venta es definitiva
Handlers.OnSaleCompleted = function(data) if data.settlementPending then return end -- repartidor / en persona: espera al hook final TriggerEvent('yourxp:addXP', data.sellerId, math.floor(data.basePrice / 100))endCómo probarlo
- Con el registrador activo y
Config.Debug = true, ejecuta/markettest listing mailbox fixed bread 50. - Date dinero si hace falta:
/markettest grant 1000. - Abre el marketplace y compra el anuncio Test item: bread.
- La consola muestra
OnSaleCompletedcondeliveryMode = mailboxystage = settled. - Repite con
/markettest listing npc fixed bread 50para verstage = committedysettlementPending = true.
OnAuctionEnded
Sección titulada «OnAuctionEnded»Cuándo: una subasta ascendente o a ciegas llega a su hora de fin con al menos una puja. El script revisa las subastas terminadas cada 30 segundos, así que puede dispararse hasta 30 s después de la hora de fin. El objeto ya está en el buzón del ganador (o en el punto de recogida) y el dinero en el buzón del vendedor.
Una subasta que termina sin pujas dispara OnListingExpired.
| Campo | Significado |
|---|---|
winnerSource, winnerId, winnerName |
La puja más alta |
sellerSource, sellerId, sellerName |
El vendedor |
item, itemLabel, itemMetadata, category, rarity, quantity |
El objeto |
winningBid / grossPrice |
Puja ganadora |
platformFee, sellerPayout |
Comisión y lo que recibe el vendedor |
finalPrice |
Alias antiguo de sellerPayout |
listingType |
'auction' o 'blind' |
deliveryMode, meetupPoint |
Cómo lo recoge el ganador |
stage |
'settled' |
listingId |
ID del anuncio |
Ejemplo: anunciar las subastas grandes en el chat
Handlers.OnAuctionEnded = function(data) if data.winningBid >= 100000 then TriggerClientEvent('chat:addMessage', -1, { args = { 'Casa de subastas', ('%s ganó %s por $%s'):format(data.winnerName, data.itemLabel, data.winningBid) } }) endendCómo probarlo
/markettest listing mailbox auction bread 100crea una subasta de prueba que termina en 5 minutos.- Puja desde tu cuenta.
- Espera 5 minutos (más hasta 30 s). La consola muestra
OnAuctionEndedy tu cliente recibesl-marketplace:onAuctionWon.
OnReverseOfferAccepted
Sección titulada «OnReverseOfferAccepted»Cuándo: en una subasta inversa (un comprador publica “busco X, hasta $Y”), el comprador acepta la oferta de uno de los vendedores. El objeto del vendedor pasa al comprador, se paga al vendedor y se devuelve el resto del depósito del comprador.
| Campo | Significado |
|---|---|
buyerSource, buyerId, buyerName |
Autor de la solicitud (el que paga) |
sellerSource, sellerId, sellerName |
El vendedor cuya oferta se aceptó |
item, itemLabel, itemMetadata, quantity |
El objeto |
grossPrice |
Oferta aceptada |
platformFee, sellerPayout |
Comisión y lo que recibe el vendedor |
depositRefund |
Parte del depósito que se devuelve al comprador |
messageId, listingId |
La oferta y la solicitud |
stage |
'settled' |
Cómo probarlo: dos jugadores. A crea un anuncio inverso; B le envía una oferta desde el anuncio; A la acepta. Antes se ejecuta CanBuyListing con action = 'accept_reverse_offer'.
Anuncios
Sección titulada «Anuncios»OnListingCreated
Sección titulada «OnListingCreated»Cuándo: se ha publicado un anuncio de cualquier tipo (el objeto ya ha salido del inventario del vendedor). El cliente del vendedor recibe también sl-marketplace:onListingCreated.
| Campo | Significado |
|---|---|
sellerSource, sellerId, sellerName |
El vendedor |
item, itemLabel, itemKind, itemMetadata, category, rarity, quantity |
El objeto |
price / basePrice |
Precio o precio de salida |
buyNowPrice |
Precio de Buy Now, o nil |
listingType |
'fixed', 'auction', 'blind', 'dutch', 'reverse', 'bundle' o 'barter' |
deliveryMode, deliveryModes, meetupPoint |
Opciones de entrega |
featured, featuredCost |
Si se destacó y el coste |
expiresAt |
Hora de fin (segundos Unix), o nil en anuncios que no caducan |
images, bundleItems, wantedItems, wantsAny |
Contenido extra |
listingId |
ID del nuevo anuncio |
Ejemplo: registrar los anuncios destacados
Handlers.OnListingCreated = function(data) if data.featured then print(('[market] %s pagó $%d por destacar %s'):format(data.sellerName, data.featuredCost, data.itemLabel)) endendCómo probarlo: abre el marketplace, publica cualquier objeto y mira la consola.
OnListingExpired
Sección titulada «OnListingExpired»Cuándo: un anuncio con hora de fin llega a ella sin venderse. La comprobación se hace cada 30 segundos.
Solo caducan estos tipos de anuncio: subasta y subasta a ciegas sin pujas, subasta holandesa, subasta inversa y trueque. Los anuncios de precio fijo y los lotes no caducan nunca.
listingType |
Qué hace el script | returnMode |
|---|---|---|
'auction', 'blind' (sin pujas) |
Devuelve el objeto al buzón del vendedor | 'mailbox' |
'dutch' |
Devuelve el objeto al buzón del vendedor | 'mailbox' |
'barter' |
Devuelve el objeto al vendedor; rechaza todas las propuestas abiertas y devuelve sus objetos y dinero | 'mailbox' |
'reverse' |
Devuelve el depósito del comprador (si Config.Auctions.Reverse.DepositRequired) |
'deposit_refund' o 'none' |
| Campo | Significado |
|---|---|
sellerSource, sellerId, sellerName |
Dueño del anuncio |
item, itemLabel, itemMetadata, category, rarity, quantity |
El objeto |
price / basePrice |
Precio del anuncio |
listingType |
Tipo (ver arriba) |
deliveryMode, meetupPoint |
Opciones de entrega |
reason |
Por ahora siempre 'timeout' |
returnMode |
Ver arriba |
expiredAt |
Cuándo caducó (segundos Unix) |
listingId |
ID del anuncio |
Cómo probarlo: /markettest listing mailbox auction bread 100 y no pujes. A los 5 minutos (más hasta 30 s) la consola muestra OnListingExpired con returnMode = mailbox.
OnListingCancelled
Sección titulada «OnListingCancelled»Cuándo: se cancela un anuncio, por su dueño o por un administrador desde el panel. El objeto se devuelve al vendedor.
| Campo | Significado |
|---|---|
actorSource, actorId, actorName |
Quién lo canceló |
sellerSource, sellerId, sellerName |
Dueño del anuncio |
item, itemLabel, itemMetadata, quantity, price |
El anuncio |
listingType |
Tipo |
cancellationType |
'owner' o 'admin' |
listingId |
ID del anuncio |
La cancelación del dueño pasa antes por CanCancelListing; la de un administrador dispara además OnAdminAction con action = 'force_cancel'.
Cómo probarlo: publica algo y cancélalo (cancellationType = 'owner'). Después publica otra vez y cancélalo desde /marketadmin ('admin').
OnListingBumped
Sección titulada «OnListingBumped»Cuándo: un vendedor paga Config.BumpCost para volver a subir uno de sus anuncios a lo más alto de los resultados. Limitado a una vez cada 5 minutos (Config.RateLimits.bump).
| Campo | Significado |
|---|---|
sellerSource, sellerId, sellerName |
El vendedor |
item, itemLabel, quantity |
El anuncio |
cost |
Lo que pagó |
bumpedAt |
Cuándo (segundos Unix) |
listingId |
ID del anuncio |
Cómo probarlo: sube (bump) uno de tus anuncios desde el marketplace.
OnBidPlaced
Sección titulada «OnBidPlaced»Cuándo: se acepta una puja en una subasta. Se dispara con las pujas hechas a mano (bidType = 'manual') y con las pujas automáticas que hace la puja proxy en nombre de alguien (bidType = 'proxy_auto').
| Campo | Significado |
|---|---|
bidderSource, bidderId, bidderName |
Quién pujó |
sellerId, sellerName |
El vendedor |
item, itemLabel |
El objeto |
amount |
Nueva puja |
previousBid |
Puja más alta anterior |
bidType |
'manual' o 'proxy_auto' |
listingType |
'auction' o 'blind' |
listingId |
ID del anuncio |
Ejemplo: avisar al staff de subidas sospechosas
Handlers.OnBidPlaced = function(data) if data.previousBid and data.previousBid > 0 and data.amount > data.previousBid * 10 then print(('[market] salto grande en #%d: %d -> %d por %s'):format(data.listingId, data.previousBid, data.amount, data.bidderName)) endendCómo probarlo: puja en una subasta de prueba (/markettest listing mailbox auction bread 100). Para ver proxy_auto, un segundo jugador fija un máximo automático y después tú le superas.
OnProxyBidSet
Sección titulada «OnProxyBidSet»Cuándo: un jugador fija o cambia su máximo de puja automática (Config.Auctions.ProxyBidding.Enabled). El script pujará por él automáticamente hasta esa cantidad.
| Campo | Significado |
|---|---|
bidderSource, bidderId, bidderName |
El jugador |
sellerId, sellerName |
El vendedor |
maxAmount |
Su máximo |
minimumBid |
Puja mínima válida cuando lo fijó |
listingId |
ID del anuncio |
Cómo probarlo: abre una subasta de prueba y fija un máximo automático en lugar de una puja normal.
Repartidor NPC
Sección titulada «Repartidor NPC»OnDeliveryCompleted
Sección titulada «OnDeliveryCompleted»Cuándo: una furgoneta de reparto llega al comprador y le entrega el objeto; en ese momento se paga al vendedor. Es el momento final de una venta por repartidor. El cliente del comprador recibe también sl-marketplace:onDeliveryArrived y sl-marketplace:onDeliveryResult (result = 'delivered').
| Campo | Significado |
|---|---|
deliveryId |
ID del reparto |
buyerSource, buyerId, buyerName |
El comprador |
sellerSource, sellerId, sellerName |
El vendedor |
item, itemLabel, itemMetadata, quantity |
El objeto |
basePrice, grossPaid, platformFee, deliveryFee, modeSurcharge, npcDeliveryFee, insuranceFee, sellerPayout |
Campos de dinero |
price |
Alias antiguo de sellerPayout |
deliveryMode, stage |
'npc', etapa final |
listingId |
ID del anuncio |
Cómo probarlo: /markettest listing npc fixed bread 50, cómpralo y espera a la furgoneta (entre 1 y 2 minutos con los MinDistance / MaxDistance por defecto).
OnDeliveryFailed
Sección titulada «OnDeliveryFailed»Cuándo: un reparto termina sin entregar el objeto (y sin que lo atraquen). Al comprador se le reembolsa automáticamente.
reason |
Causa |
|---|---|
'timeout' |
La furgoneta no llegó dentro de Config.Gameplay.NPCDelivery.DeliveryTimeout (600 s por defecto) |
'buyer_offline' |
El comprador salió del servidor durante el reparto |
'destroyed' |
La furgoneta fue destruida |
'unknown' |
Cualquier otro fallo |
| Campo | Significado |
|---|---|
deliveryId |
ID del reparto |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
item, itemLabel, itemMetadata, quantity |
El objeto |
price / basePrice, grossPaid |
Lo que se cobró |
refundAmount |
Lo reembolsado al comprador |
deliveryFee, modeSurcharge, npcDeliveryFee, insuranceFee |
Extras |
deliveryMode, stage, reason, listingId |
Detalles |
Cómo probarlo: compra un anuncio de prueba npc y, mientras viene la furgoneta, destrúyela (destroyed) o desconéctate (buyer_offline). Para timeout, pon temporalmente DeliveryTimeout = 30 y bloquéale el camino.
OnDeliveryRobbed
Sección titulada «OnDeliveryRobbed»Cuándo: otro jugador atraca una furgoneta de reparto: fuerza el maletero (el minijuego de puntería) o, si Config.Gameplay.NPCDelivery.PoliceAlertOnKill es true, mata al conductor. Se dispara una sola vez por reparto, con lo que ocurra primero. Justo antes se ejecuta Config.OnDeliveryRobbed. El cliente del atracador recibe sl-marketplace:onDeliveryRobbed.
| Campo | Significado |
|---|---|
deliveryId |
ID del reparto |
thiefSource, thiefId, thiefName |
El atracador |
buyerId, sellerId |
Comprador y vendedor |
item, itemLabel, itemMetadata, quantity |
La carga |
value |
Valor de la carga |
trigger |
'cargo_stolen' o 'driver_killed' |
stage |
'robbed' |
listingId |
ID del anuncio |
Ejemplo: aviso a la policía
Handlers.OnDeliveryRobbed = function(data) local coords = GetEntityCoords(GetPlayerPed(data.thiefSource)) TriggerEvent('your_dispatch:alert', { code = '10-90', message = 'Atraco a una furgoneta de reparto', coords = coords, job = 'police' })endCómo probarlo: dos jugadores. El jugador B compra un anuncio por repartidor (/markettest listing npc fixed bread 50); el jugador A intercepta la furgoneta, amenaza al conductor y supera el minijuego del maletero. El pedido tiene que valer al menos MinValueForIntercept.
Intercambios en persona y trueque
Sección titulada «Intercambios en persona y trueque»OnInPersonTradeCompleted
Sección titulada «OnInPersonTradeCompleted»Cuándo: los dos jugadores han confirmado el intercambio cara a cara, en una venta con modo de entrega en persona o en un trueque. Es cuando los objetos y el dinero cambian de manos de verdad. Los dos clientes reciben sl-marketplace:onInPersonTradeCompleted.
| Campo | Significado |
|---|---|
tradeId |
ID del intercambio |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
item, itemLabel, quantity |
El objeto (nil en un trueque) |
price / basePrice |
Precio (0 en un trueque) |
grossPaid, platformFee, sellerPayout |
Dinero |
isBarter, tradeKind |
true / 'barter' o false / 'person' |
barter |
Lo que dio cada parte, en un trueque |
stage |
'settled' |
listingId |
ID del anuncio |
Cómo probarlo: dos jugadores, los dos conectados. B compra el anuncio de A eligiendo en persona, acuerdan un punto de encuentro en el chat, se reúnen allí y confirman los dos (se ejecuta CanConfirmInPersonTrade para cada uno).
OnInPersonTradeCancelled
Sección titulada «OnInPersonTradeCancelled»Cuándo: se cancela un intercambio en persona o un trueque: por cualquiera de los dos jugadores, porque uno salió de la zona de encuentro durante más de AbandonTimeoutSeconds o porque pasó TimeoutMinutes. A los dos se les reembolsa automáticamente.
| Campo | Significado |
|---|---|
tradeId |
ID del intercambio |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
item, itemLabel, quantity, price / basePrice |
El trato |
isBarter, tradeKind, stage |
Detalles |
reason |
Por qué, como texto (por ejemplo un tiempo agotado o quién lo canceló) |
listingId |
ID del anuncio |
Cómo probarlo: empieza un intercambio en persona como en el anterior y cancélalo desde el chat.
OnMeetupStatusChanged
Sección titulada «OnMeetupStatusChanged»Cuándo: el punto de encuentro de un intercambio en persona cambia de estado en el chat.
status |
Significado |
|---|---|
'proposed' |
Un jugador propuso un lugar |
'accepted' |
El otro jugador lo aceptó (aparecen el blip y los avisos) |
'declined' |
El otro jugador lo rechazó |
'cancelled' |
El autor lo retiró |
'expired' |
Nadie respondió en MeetRequestTimeoutSeconds (300 s) |
| Campo | Significado |
|---|---|
actorSource, actorId, actorName |
Quién lo cambió |
partnerSource, partnerId |
El otro jugador |
status |
Ver arriba |
tradeIds |
Intercambios que cubre este encuentro |
coords |
Lugar propuesto |
windowEndsAt |
Cuándo se cierra la ventana del encuentro |
Cómo probarlo: en un intercambio en persona, propón un lugar desde el chat y acéptalo o recházalo con el otro jugador.
OnBarterProposalCreated
Sección titulada «OnBarterProposalCreated»Cuándo: se ha enviado una propuesta de trueque o una contraoferta del vendedor (después de CanCreateBarterProposal). Los objetos y el dinero ofrecidos quedan retenidos en depósito.
| Campo | Significado |
|---|---|
actorSource, actorId |
Quién la envió |
recipientSource, recipientId |
Quién la recibe |
proposalType |
'proposal' o 'counter' |
offeredItems, wantedItems, offerAmount |
Contenido |
deliveryMode |
Modo de entrega elegido |
messageId, listingId |
IDs |
Cómo probarlo: dos jugadores; B envía una propuesta al anuncio de trueque de A y A le hace una contraoferta.
OnBarterProposalStatusChanged
Sección titulada «OnBarterProposalStatusChanged»Cuándo: una propuesta de trueque cambia de estado.
status |
Significado |
|---|---|
'accepted' |
Aceptada; se crea el intercambio |
'countered' |
Respondida con una contraoferta |
'rejected' |
Rechazada; se devuelven los objetos y el dinero ofrecidos |
'cancelled' |
Retirada por su autor |
'completed' |
El intercambio terminó |
| Campo | Significado |
|---|---|
actorSource, actorId, actorName |
Quién la cambió |
proposalFromId, proposalToId |
Autor y destinatario |
status |
Ver arriba |
messageId, tradeId, listingId |
IDs |
Cómo probarlo: sigue un trueque desde la propuesta hasta la aceptación, y otro hasta el rechazo.
Reembolsos
Sección titulada «Reembolsos»Los reembolsos necesitan Config.Refunds.Enabled = true. El comprador puede pedirlo dentro de los WindowDays (7) siguientes a la compra.
OnRefundRequested
Sección titulada «OnRefundRequested»Cuándo: un comprador abre una solicitud de reembolso (después de CanRequestRefund).
| Campo | Significado |
|---|---|
refundId, historyId |
Solicitud y compra |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
item, itemLabel, quantity |
Lo que se compró |
amount |
Cantidad pedida |
reason |
Explicación del comprador |
listingId |
ID del anuncio |
OnRefundApproved
Sección titulada «OnRefundApproved»Cuándo: se aprueba un reembolso y se devuelve el dinero al comprador. De tres formas: lo aprueba el vendedor, lo fuerza un administrador (forced = true, y se dispara también OnAdminAction) o nadie responde en AutoApproveAfterHours (72 h; se comprueba cada hora).
| Campo | Significado |
|---|---|
refundId, historyId |
Solicitud y compra |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
item, itemLabel, quantity |
Lo que se compró |
originalPrice |
Precio pagado |
amount / refundAmount |
Cantidad reembolsada |
forced |
true si lo forzó un administrador |
resolvedBy, resolutionType, status, stage |
Cómo se resolvió |
listingId |
ID del anuncio |
OnRefundRejected
Sección titulada «OnRefundRejected»Cuándo: el vendedor rechaza una solicitud de reembolso.
| Campo | Significado |
|---|---|
refundId, historyId |
Solicitud y compra |
buyerSource, buyerId, buyerName, sellerSource, sellerId, sellerName |
Los jugadores |
amount |
Cantidad pedida |
note |
La nota del vendedor |
resolvedBy |
Quién la rechazó |
listingId |
ID del anuncio |
Cómo probar los tres: dos jugadores. B compra a A y pide un reembolso (OnRefundRequested). A lo aprueba (OnRefundApproved) o lo rechaza (OnRefundRejected). Fuerza otro desde /marketadmin para ver forced = true.
OnPlayerRated
Sección titulada «OnPlayerRated»Cuándo: un comprador valora a un vendedor después de una compra.
| Campo | Significado |
|---|---|
raterSource, raterId, raterName |
Quién valora |
sellerSource, sellerId, sellerName |
A quién se valora |
stars |
De 1 a 5 |
comment |
Comentario, puede ser un texto vacío |
historyId, listingId |
Compra y anuncio |
stage |
'submitted' |
Ejemplo: premiar las reseñas
Handlers.OnPlayerRated = function(data) if #data.comment >= 20 and data.raterSource then exports.ox_inventory:AddItem(data.raterSource, 'money', 50) endendCómo probarlo: compra algo a otro jugador y valóralo.
OnMessageSent
Sección titulada «OnMessageSent»Cuándo: se envía un mensaje en el chat de un anuncio: texto normal, ofertas de precio, propuestas de trueque… El cliente del destinatario recibe sl-marketplace:onMessageReceived.
| Campo | Significado |
|---|---|
senderSource, senderId, senderName |
Remitente |
recipientSource, recipientId, recipientName |
Destinatario |
messageId, listingId |
IDs |
messageKind |
Tipo de mensaje (texto, oferta, trueque…) |
body |
Texto |
offerAmount, offeredItems, deliveryMode |
Para ofertas y propuestas |
Cómo probarlo: abre el anuncio de otro jugador y envíale un mensaje.
OnFavoriteChanged
Sección titulada «OnFavoriteChanged»Cuándo: un jugador añade o quita un anuncio de sus favoritos.
| Campo | Significado |
|---|---|
playerSource, playerId, playerName |
El jugador |
listingId |
Anuncio |
favorited |
true añadido, false quitado |
OnFollowChanged
Sección titulada «OnFollowChanged»Cuándo: un jugador sigue o deja de seguir a un vendedor.
| Campo | Significado |
|---|---|
followerSource, followerId, followerName |
El jugador |
sellerSource, sellerId |
El vendedor |
following |
true sigue, false dejó de seguir |
OnWishlistChanged
Sección titulada «OnWishlistChanged»Cuándo: un jugador añade o quita una entrada de su lista de deseos (Config.Wishlist.Enabled).
| Campo | Significado |
|---|---|
playerSource, playerId, playerName |
El jugador |
action |
'added' o 'removed' |
wishlistId |
ID de la entrada |
item, maxPrice, notifyOnce |
Lo que busca |
OnReportCreated
Sección titulada «OnReportCreated»Cuándo: un jugador reporta un anuncio (Config.Reports.Enabled). Con AutoHideThreshold (5) reportes abiertos, el anuncio se oculta hasta que lo revise un administrador.
| Campo | Significado |
|---|---|
reportId |
ID del reporte |
reporterSource, reporterId, reporterName |
Quién reportó |
sellerId, sellerName |
Vendedor reportado |
item, itemLabel, listingId |
El anuncio |
reason |
Uno de Config.Reports.Reasons |
description |
Texto del jugador |
Cómo probar los hooks sociales: desde el marketplace, marca un anuncio como favorito, sigue a un vendedor, añade un objeto a tu lista de deseos y reporta un anuncio; cada acción muestra su hook.
Perfil y buzón
Sección titulada «Perfil y buzón»OnProfileCreated
Sección titulada «OnProfileCreated»Cuándo: un jugador crea su tienda del marketplace (la primera vez que lo abre).
| Campo | Significado |
|---|---|
playerSource, playerId, playerName |
El jugador |
shopName, bio, avatarColor |
Su perfil |
lang |
Idioma elegido |
Cómo probarlo: con un personaje que nunca haya abierto el marketplace, pulsa F6 y crea la tienda. Para repetirlo, borra la fila de ese jugador de marketplace_users (solo en un servidor de pruebas).
OnProfileUpdated
Sección titulada «OnProfileUpdated»Cuándo: un jugador cambia su perfil o su escaparate.
| Campo | Significado |
|---|---|
playerSource, playerId, playerName |
El jugador |
shopName |
Nombre de la tienda |
changedFields |
Qué campos cambiaron |
profile |
El perfil después del cambio |
Cómo probarlo: edita el nombre de tu tienda o tu biografía desde tu perfil.
OnMailboxClaimed
Sección titulada «OnMailboxClaimed»Cuándo: un jugador recoge algo de su buzón del marketplace: un objeto (de una subasta, una devolución, una recogida…) o dinero (de una venta, un reembolso…).
| Campo | Significado |
|---|---|
playerSource, playerId, playerName |
El jugador |
mailboxId |
Entrada del buzón |
claimType |
'item' o 'money' |
amount |
Dinero recogido |
item, itemLabel, itemMetadata, quantity |
Objeto recogido |
meetupPoint |
Punto de recogida, si había que recogerlo allí |
reason |
Por qué estaba en el buzón |
Cómo probarlo: gana una subasta de prueba (/markettest listing mailbox auction bread 100, puja y espera 5 minutos): el objeto siempre va a tu buzón. Abre el buzón y recógelo (claimType = 'item'). Si vendes algo a otro jugador, el dinero queda en tu buzón, lo que prueba claimType = 'money'.
Administración
Sección titulada «Administración»OnAdminAction
Sección titulada «OnAdminAction»Cuándo: un administrador hace algo desde /marketadmin.
action |
Significado | Campos extra |
|---|---|---|
'force_cancel' |
Canceló un anuncio | listingId |
'ban_user' |
Bloqueó a un jugador en el marketplace | targetId |
'unban_user' |
Levantó un bloqueo | targetId |
'resolve_report' |
Resolvió un reporte | reportId |
'force_refund' |
Forzó un reembolso | refundId, listingId |
| Campo | Significado |
|---|---|
adminSource, adminId, adminName |
El administrador |
action |
Ver arriba |
targetId |
Jugador afectado |
details |
Datos extra (en un reembolso forzado: amount y sellerId) |
Ejemplo: registro de auditoría en Discord
Handlers.OnAdminAction = function(data) PerformHttpRequest(GetConvar('my_admin_webhook', ''), function() end, 'POST', json.encode({ content = ('**%s** hizo `%s` sobre %s'):format(data.adminName, data.action, tostring(data.targetId or data.listingId)) }), { ['Content-Type'] = 'application/json' })endCómo probarlo: date permisos de administrador (add_ace group.admin marketplace.admin allow), abre /marketadmin y cancela un anuncio, bloquea y desbloquea a un jugador de prueba, resuelve un reporte y fuerza un reembolso.
Callbacks de config.lua
Sección titulada «Callbacks de config.lua»Dos callbacks más antiguos están en config.lua en lugar de en handlers.lua. Siguen funcionando y se llaman junto a los hooks de arriba.
Config.Notify
Sección titulada «Config.Notify»Cuándo: cada vez que el marketplace muestra una notificación a un jugador desde el servidor. Cambia su contenido para usar tu propio sistema de notificaciones.
Config.Notify = function(src, msg, type) TriggerClientEvent('ox_lib:notify', src, { description = msg, type = type or 'inform' })endCómo probarlo: haz cualquier cosa que muestre una notificación (comprar algo, intentar una compra sin dinero) y comprueba que sale con tu sistema.
Config.OnDeliveryRobbed
Sección titulada «Config.OnDeliveryRobbed»Cuándo: exactamente cuando se dispara OnDeliveryRobbed, justo antes, una vez por reparto.
Config.OnDeliveryRobbed = function(thiefSrc, deliveryId, value, trigger) -- trigger: 'driver_killed' | 'cargo_stolen' TriggerEvent('dispatch:robbery', thiefSrc, GetEntityCoords(GetPlayerPed(thiefSrc)))endUsa uno de los dos, no ambos, o mandarás dos avisos por atraco. Se recomienda Handlers.OnDeliveryRobbed: recibe más datos y aparece en /markethandlers.