Sistema de artesanato FiveM: benches ox_inventory e artesanato personalizado

Construa artesanato no FiveM: benches de artesanato ox_inventory em data/crafting.lua com ingredientes e zonas, uma receita verificada pelo servidor personalizada e dicas anti-dupe.

Artesanato significa um jogador transforma alguns itens em outro item. Você pode usar os bancos de artesanato construídos no ox_inventory ou escrever sua própria receita em um script. Este artigo mostra ambos e depois as verificações que impedem os jogadores de duplicarem itens.

Bancos de artesanato ox_inventory

Abra ox_inventory/data/crafting.lua. Retorna uma lista de bancos. Cada banco tem uma lista de itens craftáveis e um lugar no mundo:

lua
return {
    {
        items = {
            {
                name = 'lockpick',
                ingredients = {
                    scrap_metal = 5,
                    plastic = 2,
                },
                duration = 5000,
                count = 1,
            },
            {
                name = 'bandage',
                ingredients = {
                    cloth = 2,
                },
                duration = 3000,
            },
        },
        points = {
            vec3(1087.3, -3099.4, -39.0),
        },
    },
}

O que cada campo faz:

Campo Significado
name O item que é produzido
ingredients Nomes de itens e a contagem de cada um necessária
duration Tempo de craft em milissegundos
count Quantos do resultado você obtém por craft
points Coordenadas onde o banco pode ser usado
zones Zonas de caixa para ox_target, como alternativa a points

Tudo nomeado em name ou ingredients deve existir em data/items.lua. Veja adicionando itens ao ox_inventory. Reinicie ox_inventory após editar o arquivo.

Dica: um valor de ingrediente abaixo de 1 não consome o item, ele usa essa fração de sua durabilidade. Um valor de 0.1 em uma ferramenta com durabilidade usa dez por cento dela.

Zonas em vez de pontos

Uma zona é uma caixa que o jogador pode alvejar:

lua
zones = {
    {
        coords = vec3(1087.3, -3099.4, -39.0),
        size = vec3(1.5, 1.0, 1.0),
        distance = 1.5,
        rotation = 45.0,
    },
},

Zonas precisam que ox_target esteja em execução. Procure nos exemplos em sua cópia de data/crafting.lua pelos campos exatos de sua versão, pois o formato muda entre versões. Para restringir um banco a um emprego, ox_inventory também lê groups no banco, a mesma ideia que em stashes ox_inventory.

Uma receita personalizada com verificações de servidor

Se você quiser suas próprias regras, como um nível de habilidade, um custo ou uma barra de progresso sua, escreva a receita em seu script e deixe ox_inventory apenas lidar com os itens. A parte importante é que o servidor faz tudo:

lua
-- server.lua
local crafting = {}

local recipe = {
    result = 'lockpick',
    ingredients = { scrap_metal = 5, plastic = 2 },
}

lib.callback.register('my_script:craft', function(source)
    if crafting[source] then return false end
    crafting[source] = true

    local ok = false

    -- 1. check every ingredient
    local hasAll = true
    for item, count in pairs(recipe.ingredients) do
        if exports.ox_inventory:Search(source, 'count', item) < count then
            hasAll = false
            break
        end
    end

    -- 2. check the player can carry the result
    if hasAll and exports.ox_inventory:CanCarryItem(source, recipe.result, 1) then
        -- 3. remove, then add
        local removed = {}
        local allRemoved = true
        for item, count in pairs(recipe.ingredients) do
            if exports.ox_inventory:RemoveItem(source, item, count) then
                removed[item] = count
            else
                allRemoved = false
                break
            end
        end

        if allRemoved and exports.ox_inventory:AddItem(source, recipe.result, 1) then
            ok = true
        else
            -- give back what was removed
            for item, count in pairs(removed) do
                exports.ox_inventory:AddItem(source, item, count)
            end
        end
    end

    crafting[source] = nil
    return ok
end)

O cliente pede, reproduz a barra de progresso e apenas lê a resposta:

lua
-- client.lua
if lib.progressBar({ duration = 5000, label = 'Crafting' }) then
    local ok = lib.callback.await('my_script:craft', false)
    lib.notify({ description = ok and 'Crafted' or 'Missing items', type = ok and 'success' or 'error' })
end

Para as funções de callback e notificação, veja server callbacks no ESX, QBCore e ox_lib.

Dicas anti-dupe

Artesanato é um lugar clássico para duplicação de itens, porque os itens são removidos e adicionados em duas etapas. Mantenha essas regras:

  • Apenas servidor. O servidor verifica ingredientes e dá o resultado. O cliente envia "Quero craftar receita X", nunca contagens ou nomes de itens que inventou.
  • Verifique, depois remova, depois adicione. Nunca adicione o resultado antes da remoção ter sucesso. Se a adição falhar, devolva os ingredientes.
  • Um craft por vez. Uma flag por jogador, como crafting[source] acima, para um evento spammado de executar a receita várias vezes em paralelo.
  • Verifique CanCarryItem primeiro. Um inventário cheio é a razão usual pela qual AddItem falha e o jogador perderia os ingredientes.
  • Verifique a distância. Se a receita pertencer a um banco, compare as coordenadas do jogador com o banco no servidor.
  • Limpe estado ao cair. Redefina a flag quando um jogador sai, para que uma desconexão no meio não bloqueie a receita.
lua
AddEventHandler('playerDropped', function()
    crafting[source] = nil
end)

Para mais sobre proteção de eventos, veja eventos de servidor seguro.

Lista de verificação

Sintoma Correção
Banco não aparecendo Edite data/crafting.lua, depois reinicie ox_inventory
Erros de receita na inicialização Um item em name ou ingredients está faltando em data/items.lua
Zona não faz nada ox_target deve estar em execução e os campos da zona devem corresponder à sua versão
Ingredientes perdidos, sem resultado Verifique CanCarryItem primeiro e reembolse quando AddItem falhar
Itens duplicados Mova a receita inteira para o servidor, adicione uma flag de uma por vez
Craft funciona de longe Verifique a distância do jogador ao banco no servidor

Respostas rápidas

Como adiciono um banco de artesanato ao ox_inventory?

Adicione uma entrada a ox_inventory/data/crafting.lua com items (cada um com ingredients e duration) e points ou zones para onde o banco fica. Reinicie ox_inventory.

Uma receita pode usar parte da durabilidade de um item?

Sim. Um valor de ingrediente abaixo de 1 usa essa fração da durabilidade de um item que o tem, em vez de consumir o item.

Como faço para parar os jogadores de duplicarem itens enquanto crafta?

Faça a receita inteira no servidor: verifique os ingredientes, remova-os, depois adicione o resultado e recuse-se a começar um segundo craft enquanto um está em execução para aquele jogador.

Scripts sem esse problema

Item Creator V2Crie itens usáveis com animações, props, efeitos e muito mais — sem escrever código.Ver script →Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →Quest CreatorUm editor visual de missões e diálogos com NPCs, montado nó por nó dentro do jogo.Ver script →

Continue lendo