FiveM NUI React ve Vite ile: kurulum, geri çağırmalar ve tarayıcı geliştirmesi

FiveM NUI'yi React ve Vite ile oluşturun: ui_page ve fxmanifest dosyaları, base './', SendNUIMessage, RegisterNUICallback, SetNuiFocus ve tarayıcıda geliştirme.

Düz HTML küçük bir NUI için işe yarar, ancak gerçek bir arayüz React ile daha kolaydır. İnsanları tuzağa düşüren kısım React değil, tutkal: manifest, derleme çıktısı yolları ve iletilerin geri ve ileri nasıl gideceğidir.

Bu makale, FiveM'de yüklenen, her iki yönde Lua ile konuşan ve normal bir tarayıcı sekmesinde oluşturulabilen bir React ve Vite NUI'si ayarlar.

Proje düzeni

Arayüzü kaynağın içindeki web klasörüne koyun ve Vite ile oluşturun:

bash
cd my_script
npm create vite@latest web -- --template react
cd web
npm install

Sonuç:

text
my_script/
  fxmanifest.lua
  client/main.lua
  web/
    package.json
    vite.config.js
    src/
    dist/        (created by the build)

vite.config: base './'

FiveM sayfanızı web sunucusu kökünden değil, nui:// adresinden yükler. Vite'nin varsayılan varlık yolları / ile başlar; bu daha sonra hiçbir yere işaret eder ve sizi boş bir sayfayla bırakır. Onları göreli yapın:

js
// web/vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  base: './',
  build: { outDir: 'dist' },
})

Ardından oluşturun:

bash
npm run build

fxmanifest.lua

Yerleşik index.html öğesine ui_page işaret edin ve oyuncuyla tüm dist klasörünü files ile gönderin:

lua
fx_version 'cerulean'
game 'gta5'

ui_page 'web/dist/index.html'

files {
    'web/dist/index.html',
    'web/dist/**',
}

client_script 'client/main.lua'

files öğesinde listelenen dosyalar oyunculara gönderilir. Oyunda bir resim veya yazı tipi eksikse, dosya glob'u bunu içermedi. node_modules ve src öğesini listeden çıkartın: oyuncuların onlara ihtiyacı yok.

Lua'dan UI'ye: SendNUIMessage

İstemci komut dosyası bir ileti gönderir ve arayüze odak verir:

lua
local open = false

local function setOpen(state)
    open = state
    SetNuiFocus(state, state)
    SendNUIMessage({ action = 'setVisible', visible = state, data = { name = 'Mic' } })
end

RegisterCommand('myui', function()
    setOpen(not open)
end, false)

SetNuiFocus(hasFocus, hasCursor) klavye ve fareyi sayfaya verir. Her zaman geri verin, aksi halde imleç yapışır: NUI odak yapışmış imleç bölümüne bakın.

React'te ileti için dinleyin:

jsx
import { useEffect, useState } from 'react'

export default function App() {
  const [visible, setVisible] = useState(false)
  const [name, setName] = useState('')

  useEffect(() => {
    const onMessage = (event) => {
      const { action, visible, data } = event.data
      if (action === 'setVisible') {
        setVisible(visible)
        if (data) setName(data.name)
      }
    }
    window.addEventListener('message', onMessage)
    return () => window.removeEventListener('message', onMessage)
  }, [])

  if (!visible) return null
  return <div className="panel">Hello {name}</div>
}

Gizli olduğunda hiçbir şey işlemez bir sayfa, olağan modeldir; NUI sayfası kendisi yüklü kalır.

UI'den Lua'ya: fetch ve RegisterNUICallback

Diğer yön için, sayfa kaynağınızda URL'ye POST yapar. GetParentResourceName() FiveM'in sayfaya sağladığı ve kaynak adını döndüren bir işlevdir:

js
export async function nuiPost(eventName, data = {}) {
  const resource = window.GetParentResourceName ? window.GetParentResourceName() : 'my_script'
  const resp = await fetch(`https://${resource}/${eventName}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json; charset=UTF-8' },
    body: JSON.stringify(data),
  })
  return resp.json()
}
jsx
<button onClick={() => nuiPost('close')}>Close</button>

Lua'da, bunun ile ilgilenin. Geri çağırma çağrılması gerekir, aksi halde istek beklemede kalır:

lua
RegisterNUICallback('close', function(data, cb)
    setOpen(false)   -- gives focus back
    cb({ ok = true })
end)

data kod çözülmüş JSON gövde ve cb getirmeyi yanıtlar. cb öğesine geçirilenler herhangi bir yanıt olarak geri gelir.

Tarayıcıda geliştirme

Her CSS değişikliği için yeniden oluşturmak ve kaynağı yeniden başlatmak yavaştır. Vite'ı çalıştırın ve normal bir tarayıcı sekmesinde çalışın:

bash
npm run dev

Oyun dışında, window.GetParentResourceName yok ve kimse size iletiler göndermez, bu nedenle her ikisini taklit edin:

js
export const isBrowser = !window.invokeNative

// in main.jsx, in dev only
if (isBrowser) {
  setTimeout(() => {
    window.postMessage({ action: 'setVisible', visible: true, data: { name: 'Mic' } }, '*')
  }, 500)
}

Yukarıdaki nuiPost işlevi zaten varsayılan bir kaynak adına geri döner. Tarayıcıda, istek basitçe başarısız olur, bu nedenle isBrowser doğru olduğunda bunu yakalayın veya çağrıyı atlayın. isBrowser doğru ise, çağrıyı atlayın. Sayfanın arkasındaki dünyayı oyun gösterir çünkü geliştirmede karanlık veya dama arkapalan kullanın.

Oyunun içinde yineleme

Oyunda son kontrolü yapmak için oluşturun ve yalnızca kaynağı yeniden başlatın:

bash
npm run build

ardından sunucu konsolunda ensure my_script yazın. vite build --watch ile, kaydettiğiniz her zaman dosyalar yeniden oluşturulur ve yalnızca kaynağı yeniden başlatırsınız.

Yaygın sorunlar

  • Boş sayfa. Eksik base: './', veya files web/dist/** içermiyor.
  • Tıkladığında hiçbir şey olmaz. RegisterNUICallback adı getirme URL'si ile eşleşmiyor veya cb asla çağrılmıyor.
  • Kapatmadan sonra imleç yapışır. Kaynağın yeniden başlatılması da dahil olmak üzere her kapatma yolunda SetNuiFocus(false, false) eksik.
  • Oyunda yazı tipleri ve resimler eksik. Mutlak yolla başvurulur veya dist içinde değildir.
  • İleti hiç gelmez. Sayfa henüz yüklenmedi veya action adları Lua ve dinleyici arasında farklılık gösteriyor.

Kontrol listesi

Belirti Çözüm
Oyunda boş UI, tarayıcıda çalışır vite.config base: './', ardından npm run build
Oyuncular için eksik dosyalar fxmanifest.lua files { 'web/dist/**' }
Düğme hiçbir şey yapmıyor RegisterNUICallback adını eşleştirin ve cb çağırın
Sayfadan oyuna ulaşılamaz https://${GetParentResourceName()}/name öğesine fetch
İmleç geri gelmez Kapatırken SetNuiFocus(false, false)
Oyun olmadan geliştirme vite çalıştırın, postMessage ve GetParentResourceName taklit edin

Kısa yanıtlar

React NUI'im neden FiveM'de boş sayfa?

Genellikle derleme mutlak varlık yollarını kullanır. vite.config öğesinde base: './' ayarlayın, yeniden derleyin ve fxmanifest.lua öğesindeki files tüm web/dist klasörünü içeriyor olup olmadığını kontrol edin.

UI verileri oyuna nasıl geri gönderir?

https://${GetParentResourceName()}/eventName öğesine fetch POST ile; Lua'da RegisterNUICallback('eventName', ...) ile işlenir; geri çağırmayı çağırması gerekir.

FiveM başlatmadan NUI'yi geliştirebilir miyim?

Evet. Tarayıcıda vite öğesini çalıştırın, oyunun dışında olduğunuzu algılayın ve Lua'nın gönderilecekleri taklit etmek için window.postMessage ile sahte iletiler gönderin.

Bu sorunu yaşatmayan scriptler

Mic PhoneTablete dönüşen katlanabilir bir telefon; oyuncunun gerçek telefonuna da taşınır.Scripti gör →Clothing DesignerFiveM içinde kıyafet tasarlayın — fırça, katmanlar, görsel içe aktarma ve yapay zekâ — sonra giyin.Scripti gör →Arcade MachinesGerçek kabinlerde oynanabilir yedi arcade oyunu; skor tabloları ve bahislerle.Scripti gör →

Okumaya devam edin