FiveM TypeScript resources: fxmanifest, @citizenfx types ve esbuild
FiveM resources'ları TypeScript veya JavaScript'te yazın: dist dosyaları ile fxmanifest, @citizenfx types, esbuild bundle, events, setTick ve Wait, Lua exports'ını çağırma.
FiveM script'inizde types, async/await ve npm paketleri istiyorsunuz, ancak resource'unuz sadece .lua dosyalarıdır. FiveM kendi runtime'ında JavaScript çalıştırır, bu nedenle TypeScript, JavaScript'e ilk derlendiği sürece çalışır. Bu kılavuz işçi düzeni verir: manifest, types, bundler, events ve ticks ve Lua ile nasıl karıştırılır.
Proje düzeni
my_resource/
fxmanifest.lua
package.json
tsconfig.json
src/
client.ts
server.ts
dist/ (build output, loaded by FiveM)src/ yazarsınız, dist/ öğesine derleyin ve manifest yalnızca dist/ öğesi hakkında bilir.
Fxmanifest
fx_version 'cerulean'
game 'gta5'
client_script 'dist/client.js'
server_script 'dist/server.js'Her ikisi de düz JavaScript dosyasıdır. Resource'unuz belirli bir JavaScript runtime sürümü veya server'da Node özellikleri gerekiyorsa, manifest seçenekleri için mevcut Cfx.re docs kontrol edin, desteklenen runtime'lar zaman içinde değişmiştir.
İpucu: build'i dışarıda bırakırsanız, FiveM
dist/client.jsbulamadığını söyler. Kişileştir veya yeniden başlama öncesinde her zaman build'i çalıştırın.
Types ve bundler kurun
npm init -y
npm install --save-dev typescript esbuild @citizenfx/client @citizenfx/server@citizenfx/client ve @citizenfx/server her tarafta natives ve Cfx.re fonksiyonları için type paketleridir. Onları kullanan bir tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": ["src"]
}TypeScript burada sadece type kontrol eder (noEmit). esbuild asıl bundling'i yapar:
{
"scripts": {
"build": "esbuild src/client.ts --bundle --outfile=dist/client.js --target=es2020 && esbuild src/server.ts --bundle --outfile=dist/server.js --target=es2020 --platform=node",
"watch": "npm run build -- --watch",
"typecheck": "tsc"
}
}Bundling, aldığınız npm paketlerinin tek çıktı dosyasına kopyalandığı anlamına gelir, bu nedenle server'ın runtime'da node_modules gerekmez. Runtime yapılarınızın kullandığı doğru --platform ve --target için Cfx.re docs kontrol edin.
Events
JavaScript Lua gibi dört yapı taşına sahiptir, başka adlarla:
| Lua | JavaScript |
|---|---|
AddEventHandler |
on |
RegisterNetEvent + handler |
onNet |
TriggerEvent |
emit |
TriggerServerEvent / TriggerClientEvent |
emitNet |
// src/server.ts
onNet('my_resource:requestData', () => {
const src = (global as any).source as number
emitNet('my_resource:data', src, { hello: 'world' })
})// src/client.ts
on('onClientResourceStart', (resourceName: string) => {
if (GetCurrentResourceName() !== resourceName) return
emitNet('my_resource:requestData')
})
onNet('my_resource:data', (data: { hello: string }) => {
console.log(data.hello)
})Server'da, olayı tetikleyen oyuncu, Lua gibi global source içindedir. Handler başında bunu bir sabite okuyun: await sonra, global başka bir oyuncuyu işaret edebilir. Server olaylarını güvence altına alma ile aynı güvenlik kuralları geçerli, çünkü oyuncu onNet'inizi dışarıdan ateşleyebilir. Event modeline ilişkin daha fazla bilgi client ve server events.
Ticks ve bekleme
Varsayılan olarak frame loop'u yoktur. setTick her frame'de bir fonksiyon çalıştırır ve Lua'dan Wait, setTimeout çevresinde bir promise olur:
const Delay = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms))
setTick(async () => {
const ped = PlayerPedId()
const [x, y, z] = GetEntityCoords(ped, true)
// ... check something about the position
await Delay(500) // without this, it runs every frame
})Gecikmesiz, handler her frame'de çalışır, Lua döngüsü olmadan aynı problem Wait(0): Wait ve thread'ler açıklanmış bakın. Hiçbir şey her frame'de kontrol edilmesi gerekmediğinde daha uzun bir gecikme kullanın.
Tek seferlik bir gecikme için, setTick atlayın ve sadece async fonksiyon içinde await Delay(1000) yapın.
Lua exports ile karıştırma
Exports diller arasında çalışır. JavaScript'te bir tane kaydedin:
exports('getGreeting', (name: string) => `Hello ${name}`)Ve Lua resource'ından çağırın:
local text = exports['my_resource']:getGreeting('Mic')Diğer yön, TypeScript'ten Lua export'u çağırma, exports nesnesi aracılığıyla gider:
const ok = exports['ox_inventory'].GetItemCount(source, 'bread')Türler diğer resource'u bilmiyorsa, örneğin declare const exports: Record<string, any> ile kendini beyan edin. Lua'da exports hedef resource yeniden başlatıldığında nasıl davrandığını görün.
Başlamadan önce derleyin
Çalışırken watcher'ı çalıştırın ve her build sonra resource'u konsolda yeniden başlatın:
npm run watch
restart my_resourceYeniden başlama yeni bir şey yapmazsa, çıktı dosyasının değiştiğini, manifestin onu işaret ettiğini ve resource'un cache/ içinde eski bir kopyadan sunulmadığını kontrol edin.
Kontrol listesi
| Belirti | Fix |
|---|---|
FiveM dist/client.js bulamıyor |
Build'i çalıştırın; manifest çıktıyı yükler, src/ değil |
| Natives editörde bilinmiyor | @citizenfx/client ve @citizenfx/server kurun |
import runtime'da başarısız olur |
esbuild ile bundle'layın, böylece import'lar satır içi olur |
| Handler yanlış oyuncuyu kullanıyor | Herhangi bir await öncesinde source öğesini sabite okuyun |
| Tick'ten yüksek resmon | setTick handler'a await Delay(ms) ekleyin |
| Lua işlevinizi görmüyor | exports('name', fn) ile kaydedin ve resource adıyla çağırın |
Kısa yanıtlar
TypeScript'ı bir FiveM resource'unda doğrudan kullanabilir miyim?
Hayır. FiveM JavaScript çalıştırır. TypeScript yazarsınız, esbuild gibi bir araçla düz JavaScript'e derleyin ve client_script ve server_script çıktı dosyalarını işaret edin.
Bir TypeScript resource'u Lua exports'ını çağırabilir mi?
Evet. Exports diller arasında paylaşılır: JavaScript'ten exports['my_resource'].functionName() çağırın ve Lua, JavaScript'te exports('name', fn) ile kaydettiğiniz exports'ları çağırabilir.
JavaScript'te Wait() yerine ne var?
Async fonksiyon içinde setTimeout veya setTick handler'ında bir promise kullanın. Ticking loop kendisi setTick'tir ve her tick, her frame'de çalıştığı için bir gecikmeyi beklemelidir.
Bu sorunu yaşatmayan scriptler
Quest CreatorGörevler ve NPC diyalogları için oyun içinde düğüm düğüm kurulan görsel editör.Scripti gör →
Item Creator V2Animasyonlar, proplar, efektler ve daha fazlasıyla kullanılabilir eşyalar oluşturun — kod yazmadan.Scripti gör →
Shop CreatorBir dakikadan kısa sürede dükkân kurun — sahipler, çalışanlar, kasalar ve soygunlar dahil.Scripti gör →