วิธีสร้าง Resource FiveM ตัวแรก ตั้งแต่ Folder ว่างจนรัน Script ได้จริง
การสร้าง Resource FiveM ตัวแรก ไม่ได้ซับซ้อนอย่างที่หลายคนคิด เพราะ Resource ขั้นพื้นฐานต้องมีเพียง Folder, fxmanifest.lua และ Script ที่ต้องการให้ FiveM โหลด เช่น client.lua หรือ server.lua
โครงสร้างง่ายที่สุดสามารถเป็น
my_first_resource/
├── fxmanifest.lua
├── client.lua
└── server.lua
จากนั้นเขียน fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
server_script 'server.lua'
นำ Folder ไปไว้ใน
resources/[local]/
แล้วใช้ Server Console
refresh
ensure my_first_resource
เพียงเท่านี้ FXServer ก็สามารถค้นพบและ Start Resource ของเราได้
ในบทความนี้จะสร้าง Resource ตั้งแต่ศูนย์ พร้อม Command, Client Event, Server Event และระบบ Client ↔ Server แบบง่าย เพื่อให้เข้าใจวงจรของ FiveM Resource จริง ๆ
① เตรียม FiveM Server ก่อน
ก่อนสร้าง Resource ควรมี FXServer ที่สามารถ Start และเข้าเล่นได้แล้ว
โครงสร้างโดยทั่วไปจะมี
server-data/
├── server.cfg
└── resources/
Folder สำคัญสำหรับการเขียน Script คือ
resources/
เพราะ FXServer จะค้นหา Resources จากบริเวณนี้
② Resource คือ Folder หนึ่งชุด
สมมติเราจะสร้าง Resource ชื่อ
my_first_resource
ให้สร้าง
resources/
└── [local]/
└── my_first_resource/
[local] เป็น Category Folder ที่นิยมใช้เก็บ Resource ที่เขียนเอง
ชื่อ Category ไม่บังคับ
คุณอาจใช้
[custom]
[scripts]
[jobs]
[core]
ก็ได้
③ ทำไมใช้ [local]
ข้อดีคือช่วยแยก
Resource ที่มากับ Server
ออกจาก
Resource ที่เราเขียนเอง
ตัวอย่าง
resources/
├── [system]
├── [gameplay]
└── [local]
├── my_first_resource
├── my_garage
└── my_job
เมื่อ Server ใหญ่ขึ้น การจัด Folder ตั้งแต่แรกช่วยให้ดูแลง่ายขึ้นมาก
④ สร้าง fxmanifest.lua
ภายใน my_first_resource สร้างไฟล์
fxmanifest.lua
ดังนั้นตอนนี้จะเป็น
my_first_resource/
└── fxmanifest.lua
ไฟล์นี้ทำให้ FiveM รู้ว่า Folder ดังกล่าวเป็น Resource และต้องโหลดอะไรบ้าง
⑤ เขียน Manifest ขั้นต่ำ
เปิด fxmanifest.lua แล้วใส่
fx_version 'cerulean'
game 'gta5'
นี่คือ Header พื้นฐานของ FiveM Resource ปัจจุบัน
cerulean คือ FXv2 Resource Version
ส่วน
game 'gta5'
หมายถึง Resource ใช้ GTA V/FiveM API Set
⑥ เพิ่ม Metadata
สามารถเพิ่ม
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
รวมเป็น
fx_version 'cerulean'
game 'gta5'
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
Metadata ไม่ได้ทำให้ Script มี Feature เพิ่ม แต่ช่วยให้ Resource อ่านง่ายและดูเป็นระบบ
⑦ สร้าง client.lua
สร้างไฟล์
client.lua
ตอนนี้ Folder จะเป็น
my_first_resource/
├── fxmanifest.lua
└── client.lua
แล้วเพิ่มใน Manifest
client_script 'client.lua'
Manifest จะเป็น
fx_version 'cerulean'
game 'gta5'
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
client_script 'client.lua'
⑧ Client Script ทำงานตรงไหน
client.lua ทำงานบน FiveM Client ของ Player แต่ละคน
เหมาะกับสิ่งที่เกี่ยวข้องกับ
PlayerPedId
Controls
Camera
HUD
Marker
NUI
Local Game World
ตัวอย่างง่ายที่สุด
print('Hello from client')
เมื่อ Resource ถูกโหลดฝั่ง Player ข้อความจะปรากฏใน Client Console/F8
⑨ สร้าง Command ตัวแรก
ใน client.lua
RegisterCommand(
'hello',
function()
print(
'Hello FiveM'
)
end,
false
)
เข้า Server แล้วพิมพ์
/hello
จะทำให้ข้อความ
Hello FiveM
ปรากฏใน Client Console
⑩ RegisterCommand คืออะไร
โครงสร้างหลักคือ
RegisterCommand(
commandName,
handler,
restricted
)
ตัวอย่าง
RegisterCommand(
'test',
function()
print('Working')
end,
false
)
false หมายถึง Command นี้ไม่ได้ใช้ ACE Restricted Command Policy
⑪ ทดสอบ PlayerPedId
ลองเพิ่ม Command
RegisterCommand(
'myped',
function()
local ped =
PlayerPedId()
print(
'My ped:',
ped
)
end,
false
)
PlayerPedId() คืน Local Player Ped Handle
นี่เป็นตัวอย่างแรกของการเรียก FiveM/GTA Native จาก Client Script
⑫ ทดสอบ Coordinates
เพิ่ม
RegisterCommand(
'mycoords',
function()
local ped =
PlayerPedId()
local coords =
GetEntityCoords(
ped
)
print(
coords
)
end,
false
)
ตอนใช้
/mycoords
Client จะอ่านตำแหน่ง Player ปัจจุบัน
⑬ ตอนนี้ Resource มีอะไรแล้ว
โครงสร้าง
my_first_resource/
├── fxmanifest.lua
└── client.lua
Manifest
fx_version 'cerulean'
game 'gta5'
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
client_script 'client.lua'
เพียงเท่านี้ก็เป็น Client-only Resource ที่ใช้งานได้แล้ว
⑭ เพิ่ม server.lua
สร้าง
server.lua
โครงสร้าง
my_first_resource/
├── fxmanifest.lua
├── client.lua
└── server.lua
เพิ่ม Manifest
server_script 'server.lua'
รวมเป็น
fx_version 'cerulean'
game 'gta5'
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
client_script 'client.lua'
server_script 'server.lua'
⑮ server.lua ทำงานที่ไหน
ทำงานบน FXServer
เหมาะกับ
Database
Permissions
Money
Inventory
Server Validation
Player Data
Global State
สิ่งที่ต้องเป็น Authority ไม่ควรโยนไปไว้ Client เพียงเพราะเขียนง่ายกว่า
⑯ ทดสอบ Server Script
ใส่ใน server.lua
print(
'My first resource server loaded'
)
เมื่อ Resource Start ข้อความนี้ควรปรากฏใน Server Console
จึงสามารถแยกง่าย ๆ ว่า
client.lua
→ F8 / Client
server.lua
→ FXServer Console
⑰ สร้าง Server Command
ใน server.lua
RegisterCommand(
'serverhello',
function(source)
print(
'Command source:',
source
)
end,
false
)
ถ้า Player ใช้ Command ค่า source จะเป็น Server ID ของ Player
ส่วนถ้ารันจาก Server Console ค่า Source มี Behavior ที่แตกต่างและควรตรวจตาม Use Case
⑱ source สำคัญอย่างไร
ใน Server Event หรือ Server Command
local src = source
มักหมายถึง Player ที่เป็นต้นทาง
เช่น
local playerName =
GetPlayerName(src)
แล้ว
print(
src,
playerName
)
source เป็นข้อมูลสำคัญมากสำหรับ Server Logic
⑲ Client กับ Server คุยกันอย่างไร
FiveM ใช้ Network Events
พื้นฐาน Client → Server คือ
TriggerServerEvent
ส่วน Server รับด้วย
RegisterNetEvent
ตัวอย่าง Flow
Client
↓
TriggerServerEvent
↓
Network
↓
Server
↓
RegisterNetEvent Handler
⑳ สร้าง Client → Server Event ตัวแรก
ใน client.lua
RegisterCommand(
'pingserver',
function()
TriggerServerEvent(
'my_first_resource:ping'
)
end,
false
)
จากนั้น Server ต้องมี Handler
㉑ รับ Event ฝั่ง Server
ใน server.lua
RegisterNetEvent(
'my_first_resource:ping',
function()
local src =
source
print(
'Ping from player:',
src
)
end
)
เมื่อ Player พิมพ์
/pingserver
Client จะ Trigger Event ไป Server
แล้ว Server Console จะแสดง Player ID
㉒ ทำไมใช้ชื่อ Event ยาว
แทน
ping
ควรใช้ Namespace เช่น
my_first_resource:ping
ช่วยลดโอกาสชื่อชนกับ Resource อื่น
Resource จริงอาจใช้
garage:storeVehicle
inventory:useItem
job:startMission
หรือ Prefix ที่เป็นชื่อ Resource
㉓ ส่ง Parameter ไป Server
Client
TriggerServerEvent(
'my_first_resource:hello',
'FiveM'
)
Server
RegisterNetEvent(
'my_first_resource:hello',
function(message)
local src =
source
print(
src,
message
)
end
)
FiveM จะ Serialize Parameters แล้วส่งผ่าน Network Event
㉔ อย่าเชื่อ Parameter จาก Client
นี่คือหลัก Security ที่ควรเรียนตั้งแต่ Resource แรก
สมมติ Client ส่ง
TriggerServerEvent(
'shop:buy',
1
)
ไม่ได้หมายความว่า Server ควรเชื่อราคา 1
Server ควรหา Price จาก Server-side Config หรือ Database เอง
㉕ ตัวอย่าง Event ที่ไม่ควรเขียน
RegisterNetEvent(
'money:add',
function(amount)
AddMoney(
source,
amount
)
end
)
เพราะ Client สามารถพยายามส่ง
amount = 999999999
ได้
Resource แรกควรเรียน Security Principle ไปพร้อมกับ Syntax
㉖ Server ควรเป็นคนตัดสิน
ตัวอย่างที่ดีกว่า
local Reward =
500
RegisterNetEvent(
'mission:complete',
function()
local src =
source
-- ตรวจ mission state
-- ตรวจ position
-- ตรวจ cooldown
local reward =
Reward
-- จ่าย reward
end
)
Client ขอ Action
Server ตรวจและตัดสินผล
㉗ Server ส่ง Event กลับ Client อย่างไร
ใช้
TriggerClientEvent(
eventName,
playerId,
...
)
เช่น
TriggerClientEvent(
'my_first_resource:response',
src,
'Hello from server'
)
ฝั่ง Client ต้อง Register Event
㉘ สร้าง Server → Client Event
server.lua
RegisterNetEvent(
'my_first_resource:ping',
function()
local src =
source
TriggerClientEvent(
'my_first_resource:pong',
src,
'Pong!'
)
end
)
client.lua
RegisterNetEvent(
'my_first_resource:pong',
function(message)
print(
message
)
end
)
㉙ Flow Ping-Pong
ตอน Player ใช้
/pingserver
จะเกิด
Client Command
↓
TriggerServerEvent
↓
Server Handler
↓
TriggerClientEvent
↓
Client Handler
↓
Pong!
นี่เป็นพื้นฐาน Networking ของ FiveM Resource จำนวนมาก
㉚ เพิ่ม config.lua
Resource เริ่มใหญ่ขึ้นควรแยก Configuration
สร้าง
config.lua
โครงสร้าง
my_first_resource/
├── fxmanifest.lua
├── config.lua
├── client.lua
└── server.lua
㉛ เขียน config.lua
Config = {}
Config.Command =
'helloresource'
Config.Message =
'My first FiveM resource'
ถ้าทั้ง Client และ Server ใช้ ให้ประกาศ
shared_script 'config.lua'
㉜ Manifest หลังมี Shared Config
fx_version 'cerulean'
game 'gta5'
author 'Your Name'
description 'My first FiveM resource'
version '1.0.0'
shared_script 'config.lua'
client_script 'client.lua'
server_script 'server.lua'
ทั้ง Client และ Server จะโหลด config.lua
แต่จำว่าเป็นคนละ Runtime
㉝ Shared ไม่ใช่ Shared Memory
Client ทำ
Config.Message =
'Changed by client'
ไม่ได้ทำให้ Server เห็นค่าที่เปลี่ยนโดยอัตโนมัติ
ทั้งสองฝั่งเพียงโหลด Source Code จากไฟล์เดียวกัน
ถ้าต้อง Sync Runtime State ต้องใช้
Events
State Bags
Callbacks
Database
ตาม Requirement
㉞ ใช้ Config กับ Command
client.lua
RegisterCommand(
Config.Command,
function()
print(
Config.Message
)
end,
false
)
ตอนนี้ชื่อ Command ไม่ Hardcode อยู่ใน Client Logic
แก้ใน config.lua จุดเดียวได้
㉟ ตั้งชื่อ Resource อย่างไรดี
ควร
สั้น
อ่านง่าย
ไม่ซ้ำ
อธิบายหน้าที่
เช่น
com_garage
com_jobs
city_inventory
police_tools
หลีกเลี่ยงชื่อมั่วอย่าง
newscript2-final-fixed-real
เพราะ Resource Name ถูกใช้อ้างใน Exports, Dependencies และ Logs
㊱ ใช้ขีดกลางหรือ underscore
FiveM รองรับชื่อ Resource หลากหลายแบบ แต่ควรเลือก Convention เดียวทั้ง Project
เช่น
my-garage
หรือ
my_garage
แล้วใช้สม่ำเสมอ
โดยเฉพาะเมื่อชื่อ Resource ถูก Hardcode ใน API หรือ NUI
㊲ Resource พร้อมแล้ว Start อย่างไร
ถ้าเพิ่ง Copy Folder เข้า resources/ ขณะที่ Server ทำงานอยู่ ให้ใช้ Console
refresh
คำสั่งนี้จะ Rescan Resource Folder และ Manifests
จากนั้น
ensure my_first_resource
㊳ refresh ทำอะไร
refresh จะ Scan Resource Folder ใหม่และโหลด Resource Manifests
จึงเหมาะเมื่อเพิ่งเพิ่ม Resource ใหม่
เช่น
resources/[local]/my_first_resource
แล้ว FXServer ยังไม่รู้จัก
ให้ใช้
refresh
ก่อน
㊴ ensure ทำอะไร
ensure มี Behavior คือ
Resource ยังไม่ Start
→ Start
Resource Start อยู่
→ Restart
จึงสะดวกมากใน Development
ใช้
ensure my_first_resource
㊵ start ใช้แทน ensure ได้ไหม
ได้ถ้า Resource ยัง Stopped
start my_first_resource
แต่ถ้ากำลังทำงานอยู่ start ไม่ได้มี Behavior เหมือน ensure
ในการตั้ง server.cfg มักนิยม
ensure my_first_resource
㊶ restart ใช้ตอนไหน
หลังแก้ Script สามารถใช้
restart my_first_resource
เพื่อ Stop แล้ว Start Resource ใหม่
ไม่จำเป็นต้อง Restart FXServer ทั้งเครื่องทุกครั้ง
ช่วยให้ Development เร็วขึ้นมาก
㊷ stop ใช้ตอนไหน
ใช้
stop my_first_resource
เมื่อไม่ต้องการให้ Resource ทำงาน
Resource ที่ดีควรรองรับ Stop โดยไม่ทิ้ง
Entity
NUI Focus
Camera
Blip
Runtime State
ที่ไม่ควรค้าง
㊸ เพิ่ม Resource ลง server.cfg
เมื่อทดสอบแล้วต้องการให้ Resource Start ทุกครั้งที่ Server เปิด
เพิ่ม
ensure my_first_resource
ใน server.cfg
ตัวอย่าง
ensure mapmanager
ensure chat
ensure my_first_resource
เมื่อ FXServer Start Resource จะถูก Start ตาม Configuration
㊹ Server Console บอก Started Resource หมายถึงจบไหม
ไม่
คำว่า Resource Started หมายถึง Runtime ถูกโหลดสำเร็จระดับหนึ่ง
ยังต้องทดสอบ Feature จริง
เช่น
Command ทำงานไหม?
Event ทำงานไหม?
Client Error ไหม?
Server Error ไหม?
Restart แล้วทำงานไหม?
Resource อาจ Start ผ่านแต่ Error ตอน Player เรียก Function ได้
㊺ ดู Client Error ที่ไหน
ใช้
F8
เพื่อเปิด FiveM Client Console
Client-side Errors เช่น
attempt to index a nil value
No such export
NUI error
Native error
มักตรวจได้ที่นี่
㊻ Server Error ดูที่ไหน
ดู FXServer Console หรือ txAdmin Console
ตัวอย่าง Error
SCRIPT ERROR
พร้อม Resource และ File/Line ที่เกี่ยวข้อง
ควรอ่าน Error ตั้งแต่บรรทัดแรก ไม่ใช่ Restart Resource ซ้ำอย่างเดียว
㊼ เพิ่ม Debug Print อย่างไร
Client
print(
'[my_first_resource] client loaded'
)
Server
print(
'[my_first_resource] server loaded'
)
ช่วยแยกว่าฝั่งใดถูกโหลดจริง
สำหรับ Resource ใหญ่ควรมี Logging Convention ที่ชัดเจน
㊽ ตรวจ Resource Name ใน Runtime
ใช้
local resourceName =
GetCurrentResourceName()
print(
resourceName
)
ช่วย Debug กรณี Resource ถูก Rename
และมีประโยชน์ใน Lifecycle Events
㊾ onResourceStart คืออะไร
Resource สามารถรู้ว่าตัวเองเริ่มทำงานเมื่อไร
AddEventHandler(
'onResourceStart',
function(resourceName)
if resourceName ~=
GetCurrentResourceName() then
return
end
print(
'Resource started'
)
end
)
เหมาะกับ Server Initialization
㊿ onResourceStop สำคัญอย่างไร
Resource ที่สร้าง State หรือ Entity ควร Cleanup
AddEventHandler(
'onResourceStop',
function(resourceName)
if resourceName ~=
GetCurrentResourceName() then
return
end
print(
'Resource stopping'
)
end
)
ใน Resource ขั้นสูงอาจใช้เพื่อ
Delete temporary entities
Reset NUI
Stop temporary systems
Clear runtime state
51 Client มี Lifecycle Event ด้วยไหม
มี Event ใน Client Context เช่น onClientResourceStart และ onClientResourceStop
ตัวอย่าง
AddEventHandler(
'onClientResourceStart',
function(resourceName)
if resourceName ~=
GetCurrentResourceName() then
return
end
print(
'Client resource ready'
)
end
)
ช่วยทำ Client Initialization หลัง Resource Start
52 อย่าใช้ CreateThread ถ้าไม่จำเป็น
Resource แรกมักถูกสอนให้เขียน
CreateThread(function()
while true do
Wait(0)
-- code
end
end)
แต่ไม่ได้หมายความว่าทุก Resource ต้องมี Infinite Loop
ถ้า Logic ทำงานจาก Command หรือ Event ให้ใช้ Event-driven Pattern ได้เลย
ช่วยลด CPU Work
53 ถ้าต้องใช้ Thread ต้องมี Wait
ตัวอย่าง
CreateThread(function()
while true do
Wait(1000)
print(
'Tick'
)
end
end)
อย่าเขียน Infinite Loop โดยไม่มี Yield
while true do
-- no Wait
end
เพราะสามารถทำให้ Script/Client มีปัญหาอย่างรุนแรง
54 Resource ตัวแรกควรใช้ Framework ไหม
แนะนำให้เริ่ม Standalone ก่อน
เรียน
Resource
Manifest
Client
Server
Commands
Events
Natives
ให้เข้าใจก่อน
จากนั้นจึงเรียน
ESX
QBCore
Qbox
ox_lib
เพราะ Framework ไม่ได้แทนพื้นฐานของ FiveM
55 ทำไม Standalone สำคัญ
ถ้าเริ่มจาก Framework อย่างเดียว ผู้เรียนอาจจำเพียง
ESX.GetPlayerFromId
QBCore.Functions.GetPlayer
แต่ไม่เข้าใจว่า
source
RegisterNetEvent
TriggerClientEvent
Resource
fxmanifest
ทำงานอย่างไร
เมื่อ Framework เปลี่ยนจะ Debug ยากมาก
56 Resource ตัวแรกต้องใช้ Database ไหม
ไม่จำเป็น
สำหรับ Resource แรกควรให้
Command
↓
Client Event
↓
Server Event
↓
Client Response
ทำงานให้ครบก่อน
หลังจากนั้นค่อยเพิ่ม Database
หัวข้อ 451 เป็นต้นไปจะเข้าสู่ Database โดยตรง
57 Resource ตัวแรกต้องใช้ OneSync ไหม
Resource ง่าย ๆ ที่เป็น Command/Event ไม่จำเป็นต้องประกาศ /onesync
อย่าเพิ่ม
dependency '/onesync'
เพียงเพราะเห็น Resource อื่นใส่
เพิ่มเมื่อ Resource ต้องพึ่ง State Awareness เช่น
Routing Bucket
Server-side Entity State
OneSync-specific systems
จริง ๆ
58 ตัวอย่าง Resource ตัวแรกฉบับสมบูรณ์
โครงสร้าง
resources/
└── [local]/
└── com_first/
├── fxmanifest.lua
├── config.lua
├── client.lua
└── server.lua
fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
author 'comsiam'
description 'My first FiveM resource'
version '1.0.0'
shared_script 'config.lua'
client_script 'client.lua'
server_script 'server.lua'
config.lua
Config = {}
Config.Command =
'helloresource'
Config.WelcomeMessage =
'My first resource is working'
client.lua
AddEventHandler(
'onClientResourceStart',
function(resourceName)
if resourceName ~=
GetCurrentResourceName() then
return
end
print(
'[com_first] client started'
)
end
)
RegisterCommand(
Config.Command,
function()
TriggerServerEvent(
'com_first:hello'
)
end,
false
)
RegisterNetEvent(
'com_first:welcome',
function(message)
print(
message
)
end
)
server.lua
AddEventHandler(
'onResourceStart',
function(resourceName)
if resourceName ~=
GetCurrentResourceName() then
return
end
print(
'[com_first] server started'
)
end
)
RegisterNetEvent(
'com_first:hello',
function()
local src =
source
local playerName =
GetPlayerName(src)
or ('Player %s')
:format(src)
print(
('Hello request from %s')
:format(
playerName
)
)
TriggerClientEvent(
'com_first:welcome',
src,
Config.WelcomeMessage
)
end
)
59 วิธีติดตั้ง Resource ตัวอย่าง
นำ Folder
com_first
ไปไว้ที่
resources/[local]/com_first
ถ้า Server เปิดอยู่แล้ว ใช้
refresh
จากนั้น
ensure com_first
เข้าเกมแล้วพิมพ์
/helloresource
ควรเกิด Flow
Player Command
↓
client.lua
↓
TriggerServerEvent
↓
server.lua
↓
หา Player Name
↓
TriggerClientEvent
↓
client.lua
↓
แสดง Welcome Message
เมื่อระบบนี้ทำงาน แปลว่าคุณเข้าใจพื้นฐาน Resource, Client, Server และ Network Event ครบวงจรแล้ว
⑥⓪ Checklist ก่อนบอกว่า Resource ตัวแรกสำเร็จ
ตรวจให้ครบ
① Folder อยู่ใน resources หรือไม่?
② fxmanifest.lua อยู่ Root หรือไม่?
③ ชื่อไฟล์ถูกต้องหรือไม่?
④ fx_version เป็น cerulean หรือไม่?
⑤ game เป็น gta5 หรือไม่?
⑥ client.lua มีจริงหรือไม่?
⑦ server.lua มีจริงหรือไม่?
⑧ config.lua มีจริงหรือไม่?
⑨ Manifest Paths ถูกหรือไม่?
⑩ refresh แล้วหรือยัง?
⑪ ensure ชื่อ Resource ถูกหรือไม่?
⑫ Server Console มี Error หรือไม่?
⑬ F8 มี Error หรือไม่?
⑭ Client Command ทำงานหรือไม่?
⑮ TriggerServerEvent ทำงานหรือไม่?
⑯ RegisterNetEvent ฝั่ง Server รับได้หรือไม่?
⑰ source ถูกต้องหรือไม่?
⑱ TriggerClientEvent ส่งกลับถูก Player หรือไม่?
⑲ Client รับ Response ได้หรือไม่?
⑳ Restart Resource แล้วยังทำงานหรือไม่?
㉑ Client Input ถูกมองว่าไม่เชื่อถือหรือไม่?
㉒ Event Name มี Namespace หรือไม่?
㉓ Infinite Loop มี Wait หรือไม่?
㉔ Resource Stop มี Cleanup หากจำเป็นหรือไม่?
㉕ พร้อมเพิ่ม Feature ถัดไปหรือยัง?
ปัญหาที่พบบ่อยตอนสร้าง Resource FiveM ตัวแรก
Couldn't find resource
ตรวจว่า Folder อยู่ใน resources/
จากนั้น
refresh
แล้ว
ensure resource_name
อีกครั้ง
Resource ไม่มี fxmanifest.lua
ตรวจชื่อไฟล์ว่าเป็น
fxmanifest.lua
จริง
ไม่ใช่
fxmanifest.lua.txt
Failed to load script
ตรวจ Path ใน Manifest
เช่น
client_script 'client.lua'
แต่ File จริงอยู่
client/main.lua
ก็ต้องเปลี่ยน Manifest ให้ตรง
Command ไม่ทำงาน
ตรวจ
Resource Start หรือยัง?
client.lua ถูกโหลดไหม?
RegisterCommand ชื่อถูกไหม?
F8 มี Error หรือไม่?
TriggerServerEvent ไม่ทำงาน
ตรวจว่า Server มี
RegisterNetEvent(
'ชื่อเดียวกัน',
function()
end
)
ชื่อ Event ต้องตรงทุกตัวอักษร
Server ส่งกลับแล้ว Client ไม่รับ
ตรวจว่า Client Register
RegisterNetEvent(
'ชื่อ event',
function(...)
end
)
และ TriggerClientEvent() ใช้ Player ID ที่ถูกต้อง
แก้ Script แล้วไม่เปลี่ยน
ใช้
restart resource_name
หรือ
ensure resource_name
ตามสถานะ Resource
เพิ่ม Resource ใหม่แล้ว Server ไม่เห็น
ใช้
refresh
เพื่อ Rescan Resources
คำถามที่พบบ่อยเกี่ยวกับการสร้าง Resource FiveM
Resource FiveM ตัวแรกต้องมีไฟล์อะไร
ขั้นต่ำควรมี
fxmanifest.lua
และ Script อย่างน้อยหนึ่งไฟล์ตามระบบที่ต้องการ
Manifest พื้นฐานเขียนอย่างไร
fx_version 'cerulean'
game 'gta5'
จากนั้นเพิ่ม Client/Server Scripts
Client Script ประกาศอย่างไร
client_script 'client.lua'
Server Script ประกาศอย่างไร
server_script 'server.lua'
Shared Config ประกาศอย่างไร
shared_script 'config.lua'
Resource ควรอยู่ที่ไหน
โดยทั่วไปอยู่ใน resources/ ของ Server Data Directory
[local] จำเป็นไหม
ไม่บังคับ แต่เหมาะสำหรับจัด Resource ที่เขียนเอง
เพิ่ม Resource ใหม่ต้อง Restart Server ไหม
ไม่จำเป็นเสมอไป หาก Server กำลังทำงานสามารถใช้ refresh แล้ว Start/Ensure Resource ได้
refresh คืออะไร
Rescan Resource Folder และ Manifest Files
ensure คืออะไร
ถ้า Resource ยังไม่ Start จะ Start และถ้ากำลังทำงานจะ Restart
start ต่างจาก ensure อย่างไร
start ใช้ Start Resource ที่ Stopped ส่วน ensure ทำให้ Resource อยู่ในสถานะ Started โดย Restart หากกำลังรันอยู่
แก้ Code แล้วต้องทำอะไร
โดยทั่วไปใช้
restart resource_name
เพื่อ Reload Resource
Client Error ดูตรงไหน
ดู FiveM F8 Console
Server Error ดูตรงไหน
ดู FXServer/txAdmin Console
Client ส่งข้อมูลให้ Server อย่างไร
ใช้
TriggerServerEvent(...)
Server รับอย่างไร
ใช้
RegisterNetEvent(...)
Server ส่งกลับ Client อย่างไร
ใช้
TriggerClientEvent(...)
Client Input เชื่อถือได้ไหม
ไม่ ควร Validate ทุกข้อมูลที่มีผลกับ Gameplay, Economy หรือ Permission ฝั่ง Server
Resource แรกควรใช้ ESX หรือ QBCore เลยไหม
ไม่จำเป็น การเริ่ม Standalone ช่วยให้เข้าใจ FiveM Core APIs ก่อน
Resource แรกต้องใช้ Database ไหม
ไม่จำเป็น
Resource แรกต้องใช้ OneSync ไหม
ไม่จำเป็นถ้าไม่ได้ใช้ Feature ที่พึ่ง State Awareness
lua54 'yes' ต้องใส่ไหม
ไม่ ปัจจุบัน Lua Scripts ใช้ Lua 5.4 และ Directive นี้ Deprecated แล้ว
สรุปวิธีสร้าง Resource FiveM ตัวแรก
วิธีสร้าง Resource FiveM ตัวแรกสามารถสรุปเป็น
① สร้าง Resource Folder
↓
② สร้าง fxmanifest.lua
↓
③ สร้าง client.lua
↓
④ สร้าง server.lua
↓
⑤ ประกาศ Files ใน Manifest
↓
⑥ refresh
↓
⑦ ensure Resource
↓
⑧ ทดสอบ Client
↓
⑨ ทดสอบ Server
↓
⑩ ทดสอบ Network Events
Manifest เริ่มต้นใช้
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
server_script 'server.lua'
Client ส่ง Event ไป Server
TriggerServerEvent(
'my_resource:hello'
)
Server รับ
RegisterNetEvent(
'my_resource:hello',
function()
local src =
source
end
)
และส่งผลกลับ
TriggerClientEvent(
'my_resource:response',
src,
'Hello'
)
นี่คือวงจรพื้นฐานที่ Resource FiveM จำนวนมากใช้ แม้ Resource ระดับใหญ่จะมีหลายร้อยไฟล์ หลักพื้นฐานก็ยังเป็น
Manifest
Client
Server
Events
State
Dependencies
เหมือนเดิม
สำหรับผู้ที่เริ่มเรียน FiveM Developer กับ comsiam จุดสำคัญไม่ได้อยู่ที่การสร้าง Script ใหญ่ตั้งแต่ Resource แรก แต่คือทำให้ Resource เล็ก ๆ ตัวหนึ่ง Start, Stop, Restart และสื่อสาร Client ↔ Server ได้อย่างถูกต้องก่อน
หลักสำคัญจาก comsiam คือ Client ควรทำสิ่งที่เกี่ยวกับเครื่องผู้เล่น ส่วน Server ควรเป็นผู้ตัดสินข้อมูลสำคัญและตรวจทุก Request ที่มาจาก Client หากเข้าใจหลักนี้ตั้งแต่ Resource แรก การพัฒนา Garage, Jobs, Inventory หรือ Framework Script ภายหลังจะง่ายขึ้นมาก
หัวข้อถัดไปคือ FiveM Resource Folder จัดโครงสร้างอย่างไร ซึ่งจะต่อยอดจาก Resource ตัวแรกไปสู่การแบ่ง client/, server/, shared/, modules/, html/, stream/ และการออกแบบ Folder สำหรับ Resource ขนาดใหญ่ให้ Maintain ง่าย
Comments
Post a Comment