Konwertuj skrypt QBCore na QBox: qbx_core, ox_inventory, ox_target

Jak portować skrypt QBCore do QBox: warstwa kompatybilności qbx_core, GetPlayer, przedmioty ox_inventory, powiadomienia ox_lib i postęp, ox_target, i co zwykle się psuje.

Masz skrypt napisany dla QBCore i serwer uruchamiający QBox. Czasem się uruchamia i działa, czasem konsola się zapełnia błędami o brakujących qb-inventory, qb-target lub qb-menu. Tutaj jest kolejność, aby go portować, i miejsca, gdzie zwykle się psuje.

Jeśli wciąż wybierasz rdzeń, ta sama praca z drugiej strony jest w convert an ESX script to QBCore.

Co QBox zmienia i co przechowuje

QBox jest zbudowany na qbx_core plus zasoby Overextended: ox_lib, oxmysql, ox_inventory i ox_target. Przechowuje warstwę kompatybilności, więc exports['qb-core']:GetCoreObject() wciąż odpowiada i PlayerData ma taką samą kształt (citizenid, job, charinfo, metadata, money). Dlatego wiele skryptów działa bez zmian.

Co nie przechowuje, to stare zasoby użyteczności QB. Gdzie QBCore używał qb-inventory, qb-target, qb-menu, qb-input i qb-progressbar, QBox oczekuje ox_inventory, ox_target i ox_lib. Te są częściami, które portujesz.

Pierwszy krok to upewnienie się, że rdzeń jest uruchamiany prawidłowo:

cfg
ensure oxmysql
ensure ox_lib
ensure qbx_core
ensure ox_inventory
ensure ox_target
ensure my_script

Usuń dowolny pozostały folder qb-core, ponieważ dwa rdzenie kolidują. Zobacz QBCore is nil: GetCoreObject, jeśli obiekt brakuje.

Krok 1: zależności w manifeście

lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

shared_script '@ox_lib/init.lua'

dependencies { 'qbx_core', 'ox_lib', 'ox_inventory', 'ox_target' }

@ox_lib/init.lua to co daje ci globalny lib. Jeśli nie zostanie znaleziony, zobacz ox_lib init.lua not found.

Krok 2: uzyskanie gracza

Oba te działają na QBox. Pierwszy to styl kompatybilności, drugi to sposób QBox:

lua
-- QBCore style (still works through the compatibility layer)
local QBCore = exports['qb-core']:GetCoreObject()
local Player = QBCore.Functions.GetPlayer(source)

-- QBox style
local player = exports.qbx_core:GetPlayer(source)
if player then
    print(player.PlayerData.citizenid, player.PlayerData.job.name)
end

Oba zwracają nil dla gracza, który nie jest załadowany, więc przechowaj sprawdzenie nil. Aby znaleźć załadowanego gracza po ID obywatela, QBox ma też GetPlayerByCitizenId. Gdy portujesz, możesz zostawić wołania QBCore na miejscu i zamienić je jedno po drugim później.

Krok 3: inwentarz

To jest gdzie większość skryptów się psuje. qb-inventory i ox_inventory nie mają wspólnych definicji przedmiotów ani nazw funkcji.

Zadanie QBCore QBox z ox_inventory
Dodaj przedmiot Player.Functions.AddItem('water', 1) exports.ox_inventory:AddItem(source, 'water', 1)
Usuń przedmiot Player.Functions.RemoveItem('water', 1) exports.ox_inventory:RemoveItem(source, 'water', 1)
Liczba Player.Functions.GetItemByName('water').amount exports.ox_inventory:GetItemCount(source, 'water')
Metadane tabela info tabela metadata
lua
local src = source
local ok = exports.ox_inventory:AddItem(src, 'water', 2, { quality = 100 })
if not ok then
    lib.notify(src, { description = 'Your inventory is full', type = 'error' })
end

AddItem zwraca wartość fałszywą, gdy przedmiot nie istnieje lub nie może być niesiony, więc go sprawdzić. Definicje przedmiotów też się poruszają. QBCore przechowuje je w qb-core/shared/items.lua, ox_inventory w ox_inventory/data/items.lua. Dodaj każdy przedmiot, który skrypt używa tam, w formacie ox_inventory. Jak to zrobić jest w add items to ox_inventory, i format QBCore, z którego przychodzisz, jest w add items to qb-inventory.

Przedmioty użyteczne są też rejestrowane inaczej: QBCore.Functions.CreateUseableItem staje się export ustawionym w definicji przedmiotu w ox_inventory, który wskazuje na funkcję w twoim skrypcie. Wołania QBCore mogą wciąż działać przez warstwę kompatybilności, więc przetestuj przedmiot przed jego przepisaniem.

Krok 4: powiadomienia, postęp i menu z ox_lib

ox_lib zastępuje osobne zasoby narzędziowe QB. Wołania są zbliżone do tego, co znasz:

lua
-- QBCore
QBCore.Functions.Notify('Done', 'success', 5000)

-- ox_lib (client)
lib.notify({ title = 'Job', description = 'Done', type = 'success', duration = 5000 })
lua
-- QBCore: QBCore.Functions.Progressbar(...) with a callback
-- ox_lib: returns true when completed, false when cancelled
if lib.progressBar({
    duration = 5000,
    label = 'Repairing',
    useWhileDead = false,
    canCancel = true,
    disable = { car = true, move = true },
    anim = { dict = 'mini@repair', clip = 'fixing_a_ped' },
}) then
    print('finished')
else
    print('cancelled')
end

Menu przechodzą z qb-menu na lib.registerContext i lib.showContext, a formularze wejściowe z qb-input na lib.inputDialog. Pełne przykłady są w notifications and progress bars on ESX, QBCore and ox_lib i ox_lib context menus.

Krok 5: ox_target zamiast qb-target

qb-target przyjmuje nazwę, współrzędne i tabelę opcji w swoim własnym układzie. ox_target przyjmuje jedną tabelę:

lua
-- qb-target
exports['qb-target']:AddBoxZone('my_zone', vector3(215.0, -810.0, 30.7), 1.5, 1.5, {
    name = 'my_zone', heading = 0, minZ = 29.7, maxZ = 32.7,
}, {
    options = { { event = 'my_script:client:open', icon = 'fas fa-box', label = 'Open', job = 'police' } },
    distance = 2.0,
})

-- ox_target
exports.ox_target:addBoxZone({
    coords = vector3(215.0, -810.0, 30.7),
    size = vector3(1.5, 1.5, 3.0),
    rotation = 0,
    options = {
        { name = 'my_zone_open', icon = 'fas fa-box', label = 'Open', groups = 'police',
          onSelect = function() TriggerEvent('my_script:client:open') end },
    },
})

Zauważ event staje się onSelect (lub event wciąż działa dla zdarzenia klienta), i job staje się groups. Szczegóły są w qb-target vs ox_target i ox_target zones.

Co zwykle się psuje

  • Błędy brakujących przedmiotów. Przedmiot istnieje w pliku udostępnionym qb-core, ale nie w ox_inventory. Dodaj to.
  • No such export dla qb-inventory, qb-target lub qb-menu. Skrypt je wołuje bezpośrednio: portuj te wołania, lub nigdy się nie uruchomi.
  • Callbacki. lib.callback to styl QBox. Jeśli skrypt wciąż używa QBCore.Functions.CreateCallback, przetestuj go i przenieś go na ox_lib, jeśli się nie powiedzie: zobacz server callbacks.
  • Prace i gangi ze stopniami. QBox ma swoje własne dane pracy i grupy. Przetestuj każde sprawdzenie pracy, szczególnie sprawdzenie czuwania i porównania stopni.
  • Mieszane rdzenie. Pozostały zasób qb-core uruchomiony obok qbx_core.
  • Kolejność uruchamiania. Twój skrypt ponad ox_lib, ox_inventory lub qbx_core w server.cfg.

Lista kontrolna

Symptom Naprawa
GetCoreObject to nil Uruchom qbx_core pierwszy i usuń dowolny folder qb-core
No such export dla qb-inventory Użyj exports.ox_inventory:AddItem(source, item, count)
Przedmiot nie znaleziony Dodaj to do ox_inventory/data/items.lua
Wołania qb-target się nie powiodą Portuj na exports.ox_target:addBoxZone lub addLocalEntity
lib to nil Dodaj shared_script '@ox_lib/init.lua'
Sprawdzenie pracy zawsze fałsz Przetestuj PlayerData.job.name i stopień na QBox

Szybkie odpowiedzi

Czy skrypty QBCore działają na QBox bez zmian?

Wiele tak, ponieważ qbx_core przechowuje warstwę kompatybilności dla qb-core. Skrypty, które zależą od qb-inventory, qb-target lub qb-menu zwykle potrzebują pracy, ponieważ QBox używa ox_inventory, ox_target i ox_lib zamiast tego.

Jak uzyskać gracza na QBox?

Na serwerze, exports.qbx_core:GetPlayer(source) zwraca gracza, z taką samą tabelą PlayerData, którą znasz z QBCore.

Czy muszę przepisać wszystko, aby przenieść się na QBox?

Nie. Uruchom skrypt na QBox, przeczytaj błędy, i zamień części, które się psują: inwentarz, cel, menu i powiadomienia. Reszta, taka jak PlayerData, prace i metadane, zachowuje swój kształt.

Skrypty bez tego problemu

Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →Quest CreatorWizualny edytor questów i dialogów z NPC, budowanych węzeł po węźle w grze.Zobacz skrypt →

Czytaj dalej