Cómo funcionan las integraciones#
Clothing Creator toca muy poco fuera de sí mismo. Todo lo específico del framework está en un pequeño puente sin cifrar en custom/, y la ropa publicada llega al resto de tu servidor igual que la ropa del juego base — como drawables en el ped freemode.
Capa | Compatibles | Sin ella |
|---|---|---|
Framework | es_extended · qb-core · qbx_core | Standalone: los administradores son quienes tengan el ace |
Menú de apariencia | Cualquiera. Restaurar el atuendo tras una actualización: qs-appearance · illenium-appearance · fivem-appearance · esx_skin | Clothing Creator sigue quitando y volviendo a poner las prendas publicadas en cada publicación por sí mismo. |
Base de datos | oxmysql | Obligatorio. |
Librería | ox_lib | Obligatorio. |
Notificaciones | Los avisos propios del estudio, o cualquier recurso de notificaciones | Se usan los avisos integrados. |
Logs | Webhooks de Discord | No se envía nada. El historial de publicaciones se sigue guardando en la base de datos. |
Menús de apariencia#
No hay nada que conectar. Los menús de apariencia — illenium-appearance, qs-appearance, fivem-appearance, esx_skin, qb-clothing, rcore_clothing y el resto — listan la ropa contando los drawables que tiene un ped freemode en cada ranura, y una publicación aumenta ese número. Una prenda nueva simplemente aparece como el siguiente número de su ranura, para todos los jugadores, en el menú que ya usen. Los atuendos guardados por esos menús siguen funcionando, porque una prenda retirada deja un marcador invisible en su lugar en vez de desplazar los números que van después.
Tras la actualización de ropa de una publicación, la skin del jugador se recarga mediante el primero de estos que esté en ejecución:
TriggerEvent('qs-appearance:client:reloadSkin', true) -- qs-appearance
TriggerEvent('illenium-appearance:client:reloadSkin') -- illenium-appearance
TriggerEvent('fivem-appearance:reloadSkin') -- fivem-appearance
TriggerEvent('skinchanger:getSkin', ...loadSkin) -- esx_skinNombres de las prendas en tu menú#
Los menús muestran los drawables como números. Si el tuyo puede mostrar etiquetas, Clothing Creator escribe el nombre de cada prenda activa en qs-clothing-assets/integrations/labels.json (y un labels.lua que devuelve la misma tabla) en cada arranque y después de cada publicación o retirada:
local labels = json.decode(LoadResourceFile('qs-clothing-assets', 'integrations/labels.json'))
-- labels.male.components['11'] → every published top for the male ped
-- { { collection = 'qsc_m', localIndex = 0, name = 'Los Santos Customs Tee' }, ... }
-- labels.female.props['0'] → every published hat for the female pedPara convertir collection + localIndex en el número que usa un menú, pregúntale al juego: GetPedDrawableGlobalIndexFromCollection(ped, slot, collection, localIndex) para la ropa, GetPedPropGlobalIndexFromCollection para los props.
Notificaciones#
Los mensajes se muestran como avisos con el estilo propio del estudio. Para enviarlos por tu recurso de notificaciones, edita la función Notification en custom/client.lua:
-- custom/client.lua
function Notification(msg, type)
if GetResourceState('qs-interface') == 'started' then
return exports['qs-interface']:AddNotify(msg, type, 5000)
end
SendReactMessage('notification', { msg = msg, type = type })
endtype es info, success o error. Los mensajes del servidor llegan por la misma función.
Logs de Discord#
Tres canales, cada uno publicado como embed. Deja una URL vacía para desactivar ese canal:
Canal | Qué se envía |
|---|---|
| Importaciones de ropa addon, y cada cambio o restablecimiento de la configuración con el administrador que lo hizo. |
| Aprobaciones y rechazos. |
| Builds fallidas, ciclos de publicación fallidos y prendas cuyo archivo de textura se perdió. |
-- server/webhooks.lua
Webhooks = {
publish = 'https://discord.com/api/webhooks/...',
moderation = '',
errors = 'https://discord.com/api/webhooks/...',
}Cada publicación, retirada y reconstrucción también queda registrada en la tabla
qs_clothing_publishes— quién lo hizo, cuándo, cuánto tardó y si funcionó — haya o no un webhook configurado.
Hosts de imágenes#
Con Settings → Images → Allow any host desactivado, los enlaces de imágenes solo se aceptan de los hosts listados en custom/config.lua. Añade tu propio CDN a la lista:
-- custom/config.lua
Config.Images.AllowedHosts = {
'i.imgur.com', 'imgur.com', 'cdn.discordapp.com', 'media.discordapp.net',
'r2.fivemanage.com', 'api.fivemanage.com', 'i.ibb.co', 'raw.githubusercontent.com',
'cdn.yourserver.com',
}Los enlaces siempre los descarga el servidor, nunca el juego de un jugador, y se rechaza todo lo que no sea PNG, JPG, GIF o WebP.
Otros scripts durante una publicación#
Conviene saber dos cosas si usas scripts que trabajan con peds o routing buckets:
Routing buckets. Mientras se aplica en vivo una nueva declaración, cada jugador pasa a un routing bucket privado (
870000+ su id de servidor) — un conductor solo en su vehículo se lo lleva consigo — y vuelve a su propio bucket en cuanto su juego tiene la ropa nueva, en 30 segundos como máximo. Evita usar buckets de ese rango.Peds freemode. Una declaración en vivo necesita que ningún juego tenga modelos freemode tras la actualización. Un script que mantiene vivo su propio ped freemode — una vista previa de selección de personaje, un clon en un menú, un maniquí — impide que ese juego reciba el cambio; la publicación lo informa y la declaración espera a un reinicio o a que el servidor quede vacío.
Añadir un framework#
Dar soporte a un framework que no está en la lista requiere una carpeta y una línea:
Copia el puente más parecido
Duplica
custom/standalone(ocustom/esx/custom/qb) comocustom/myframework.Completa las funciones
server.luaindica quién es un jugador y si es administrador;client.luadebe llamar aSetFrameworkReady()una vez cargado el personaje.lua -- custom/myframework/server.lua function framework:getIdentifier(source) end -- the player's unique id function framework:playerIsAdmin(source) end -- true for staff function framework:getUserName(source) end -- first name, last name function framework:getPlayers() end -- every online source -- also: getPlayerFromId, getSourceFromIdentifier, getUserNameFromIdentifier -- and call OnPlayerLoaded(source) when a character loadsRegístralo
En
config/config.lua, asocia el nombre del recurso de tu framework con el nombre de la carpeta y luego reinicia:lua local frameworks = { ['es_extended'] = 'esx', ['qb-core'] = 'qb', ['qbx_core'] = 'qb', ['my_framework'] = 'myframework', }
En la misma tabla va un recurso de framework renombrado — ['my-esx'] = 'esx' — y types.lua documenta cada función del puente para el autocompletado de tu editor.
Idiomas#
Incluye 41 traducciones completas en locales/: árabe, bengalí, búlgaro, catalán, chino, croata, checo, danés, neerlandés, inglés, estonio, finés, francés, alemán, griego, hebreo, hindi, húngaro, indonesio, italiano, japonés, coreano, letón, lituano, malayo, noruego, persa, polaco, portugués, rumano, ruso, eslovaco, esloveno, español, suajili, sueco, tailandés, turco, ucraniano, urdu y vietnamita. Elige uno en Settings → General → Language — se aplica a todos a la vez, sin reiniciar. Para cambiar un texto, edita la clave correspondiente en locales/<code>.json; Asset Escrow deja esos archivos abiertos.



