FiveM Resource Dependency คืออะไร? dependency, Start Order และ No Such Export แก้อย่างไร
FiveM Resource Dependency คือการกำหนดว่า Resource หนึ่งต้องพึ่ง Resource หรือ Runtime Requirement อื่นก่อนจึงจะสามารถทำงานได้ถูกต้อง เช่น Garage ต้องใช้ Database Library, Inventory ต้องใช้ Core Framework หรือ Script ต้องการ OneSync ก่อนเริ่มทำงาน
ตัวอย่าง Resource my_garage ต้องใช้ oxmysql
ใน fxmanifest.lua สามารถเขียน
dependency 'oxmysql'
หรือถ้ามีหลายตัว
dependencies {
'ox_lib',
'oxmysql'
}
แนวคิดคือ
my_garage
↓
ต้องใช้
↓
oxmysql
ดังนั้น Dependency ต้องถูก Load ก่อน Resource ที่พึ่งมัน
Resource ที่มี Dependency ซับซ้อนขึ้นอาจเป็น
my_garage
├── ox_lib
├── oxmysql
├── framework
└── OneSync
Manifest สามารถประกาศ
dependencies {
'/onesync',
'ox_lib',
'oxmysql',
'my_core'
}
การจัด Dependency ถูกต้องช่วยป้องกัน Error เช่น
No such export
Resource not found
Missing dependency
Nil function
Library not initialized
และลดการแก้ปัญหาแบบผิด ๆ เช่น
Wait(5000)
เพื่อหวังว่า Resource อื่นจะ Start ทัน
① FiveM Resource Dependency คืออะไร
Dependency หมายถึง Resource A ต้องการ Resource B ก่อน
ตัวอย่าง
garage
↓
ต้องใช้ database
↓
oxmysql
ดังนั้น garage เป็น
Dependent Resource
และ oxmysql เป็น
Dependency
Resource Manifest ของ garage จึงสามารถกำหนด
dependency 'oxmysql'
เพื่อประกาศความสัมพันธ์นี้อย่างชัดเจน
② ทำไม Resource ต้องมี Dependency
เพราะ Resource หนึ่งไม่จำเป็นต้องเขียนทุกระบบเอง
ตัวอย่าง Garage อาจใช้
oxmysql
→ Database
ox_lib
→ Library/Callbacks/UI utilities
ESX/QBCore/Qbox
→ Framework Player Data
แทนการเขียนทุกอย่างใหม่
ทำให้ Resource แบ่งหน้าที่กันได้
③ Dependency ช่วยอะไร
ประโยชน์หลักคือทำให้ Resource Manager รู้ว่า
Resource B
ต้องพร้อมก่อน
Resource A
หาก my_garage ต้องใช้ oxmysql
เขียน
dependency 'oxmysql'
ดีกว่าปล่อยให้ my_garage Start แล้วค่อยเจอ Error ตอนเรียก Database
④ dependency เขียนตรงไหน
เขียนใน
fxmanifest.lua
ตัวอย่าง
fx_version 'cerulean'
game 'gta5'
dependency 'oxmysql'
server_script 'server.lua'
นี่ประกาศว่า Resource ปัจจุบันต้องใช้ oxmysql
⑤ dependencies ต่างจาก dependency อย่างไร
ถ้ามีรายการเดียว ใช้
dependency 'oxmysql'
หากมีหลายรายการใช้
dependencies {
'ox_lib',
'oxmysql'
}
ความหมายพื้นฐานเหมือนกัน
ต่างกันที่รูปแบบการเขียน
⑥ ตัวอย่าง Dependency หลาย Resource
fx_version 'cerulean'
game 'gta5'
dependencies {
'ox_lib',
'oxmysql',
'my_core'
}
shared_script 'config.lua'
client_script 'client.lua'
server_script 'server.lua'
Architecture คือ
ox_lib ─────┐
oxmysql ────┼→ my_resource
my_core ────┘
Resource ปัจจุบันต้องพึ่งทั้งสามตัว
⑦ Dependency ไม่ใช่แค่ Start Order
Start Order เป็นส่วนหนึ่ง
แต่ Dependency ยังทำหน้าที่เป็น Contract ว่า
Resource นี้ไม่ควรถูกใช้งานโดยไม่มี Resource ที่ระบุ
ดังนั้น Developer เปิด fxmanifest.lua ก็รู้ได้ทันทีว่า Resource ต้องติดตั้งอะไรบ้าง
⑧ ตัวอย่าง Resource ที่ไม่มี Dependency ประกาศ
สมมติ garage เรียก
exports.oxmysql:query(
'SELECT * FROM vehicles'
)
แต่ Manifest ไม่มี
dependency 'oxmysql'
Resource อาจพึ่งเพียง Order ใน server.cfg
ensure oxmysql
ensure garage
ซึ่งอาจทำงานได้
แต่ Manifest ไม่ได้บอก Requirement ของ Resource อย่างชัดเจน
⑨ แบบไหนดีกว่า
ถ้า Resource ต้องใช้ Dependency จริง ควรมีทั้ง Architecture ที่ชัดและ Server Configuration ที่อ่านง่าย
Manifest:
dependency 'oxmysql'
Server:
ensure oxmysql
ensure garage
ทำให้ทั้ง Resource Contract และ Startup Configuration เข้าใจได้ง่าย
⑩ Dependency กับ server.cfg ต่างกันอย่างไร
จำง่าย ๆ
fxmanifest dependency
→ บอกว่า Resource ต้องพึ่งอะไร
ส่วน
server.cfg
→ บอกว่า Server ต้อง Start/Ensure อะไร
สองอย่างเกี่ยวข้องกัน แต่ไม่ได้มีหน้าที่เหมือนกันทั้งหมด
⑪ ตัวอย่าง server.cfg ที่จัด Order ดี
# Libraries
ensure ox_lib
ensure oxmysql
# Core
ensure my_core
# Features
ensure my_inventory
ensure my_garage
ensure my_jobs
เปิด Config มาก็เห็น Architecture
Libraries
↓
Core
↓
Feature Resources
ชัดเจน
⑫ ทำไมไม่ควรจัด Resource แบบสุ่ม
ตัวอย่าง
ensure garage
ensure police
ensure oxmysql
ensure core
ensure inventory
ensure ox_lib
อาจทำให้ Debug ยาก
แม้ Manifest Dependencies ช่วยเรื่อง Relationship แต่ Server Config ที่จัดเป็น Layer ชัดเจนยัง Maintain ง่ายกว่า
⑬ Start Order คืออะไร
คือ Order ที่ Resources ถูก Start
ตัวอย่าง
① oxmysql
② my_core
③ inventory
④ garage
ถ้า garage เรียก Export จาก my_core
my_core ต้องพร้อมก่อน Garage พยายามใช้งาน API นั้น
⑭ อย่าแก้ Start Order ด้วย Wait
ตัวอย่างที่ไม่แนะนำ
CreateThread(function()
Wait(10000)
local player =
exports['my_core']:GetPlayer(1)
end)
แนวคิดคือ
รอ 10 วินาที
=
หวังว่า dependency พร้อม
นี่ไม่ใช่ Dependency Management
⑮ ทำไม Wait ไม่ใช่วิธีแก้
เพราะ
Server เร็ว
→ Dependency พร้อมใน 1 วินาที
Server ช้า
→ อาจยังไม่พร้อมใน 10 วินาที
และถ้า Dependency Start ไม่สำเร็จ
Wait 1 นาที
ก็ไม่ช่วย
ต้องแก้ Root Cause
⑯ Resource Dependency Chain คืออะไร
Dependency สามารถต่อกันหลายระดับ
เช่น
oxmysql
↓
core
↓
inventory
↓
shop
หมายถึง
shop
ต้องใช้ inventory
inventory
ต้องใช้ core
core
ต้องใช้ oxmysql
นี่เรียกว่า Dependency Chain
⑰ Dependency Chain ยาวเกินไปมีปัญหาไหม
มีได้
สมมติ
A → B → C → D → E → F
ถ้า F มีปัญหา Resources ชั้นบนจำนวนมากอาจใช้ไม่ได้
จึงควรหลีกเลี่ยง Dependencies ที่ไม่จำเป็น
Resource ควรพึ่งเฉพาะสิ่งที่ต้องใช้จริง
⑱ Circular Dependency คืออะไร
เป็น Architecture ที่
Resource A
↓
ต้องใช้ Resource B
Resource B
↓
ต้องใช้ Resource A
หรือ
A → B → C → A
เป็น Design ที่ควรหลีกเลี่ยง
เพราะแต่ละตัวต้องการอีกตัวก่อนตัวเองพร้อม
⑲ วิธีแก้ Circular Dependency
มักแก้ด้วยการแยกส่วนที่ใช้ร่วมกันออกเป็น Resource กลาง
จาก
garage ↔ inventory
เปลี่ยนเป็น
core
/ \
garage inventory
หรือสร้าง Public APIs ที่ Boundary ชัดเจน
⑳ Core Resource คืออะไร
Server จำนวนมากมี Resource กลาง เช่น
my_core
ที่ให้บริการ
Player Data
Permissions
Common APIs
Framework Bridge
Shared State
Resources อื่นพึ่ง Core
my_core
├── garage
├── inventory
├── jobs
└── housing
ต้องระวังไม่ให้ Core กลายเป็น Resource ที่รวมทุก Feature บน Server
㉑ Dependency กับ Export เกี่ยวกันอย่างไร
Resource มักพึ่ง Resource อื่นเพราะต้องเรียก Export
ตัวอย่าง
local player =
exports['my_core']
:GetPlayer(source)
ถ้า my_core ยังไม่พร้อม Export นี้ก็ไม่สามารถถูกเรียกตามที่ Resource คาดหวัง
㉒ No such export คืออะไร
Error ลักษณะ
No such export GetPlayer
in resource my_core
หมายความว่า Resource ที่ถูกเรียกไม่มี Export ตามชื่อและ Context ที่คุณกำลังเรียกในเวลานั้น
สาเหตุมีหลายอย่าง ไม่ใช่ Start Order อย่างเดียว
㉓ สาเหตุ No such export ที่พบบ่อย
ตรวจ
① Resource Name ถูกไหม?
② Resource Start แล้วไหม?
③ Export Name ถูกไหม?
④ ตัวพิมพ์ใหญ่เล็กถูกไหม?
⑤ Export เป็น Client หรือ Server?
⑥ เรียกผิด Context หรือไม่?
⑦ Resource Version เปลี่ยน API หรือไม่?
⑧ Dependency Start สำเร็จหรือไม่?
อย่าแก้ด้วย Wait() ก่อนตรวจเหล่านี้
㉔ Client Export กับ Server Export ต้องแยกกัน
สมมติ Resource ประกาศ Export ฝั่ง Server
exports(
'GetPlayer',
function(source)
-- ...
end
)
Client ไม่ควรคิดว่าจะเรียก Server Export นี้ตรง ๆ ได้เหมือนเป็น Shared Function
Client และ Server เป็นคนละ Runtime Context
㉕ Dependency ไม่ได้สร้าง RPC ให้อัตโนมัติ
การมี
dependency 'my_core'
ไม่ได้ทำให้ Client ของ Resource A สามารถเรียก Server Function ของ Resource B แบบ Local Function
ยังต้องใช้
Client Export
Server Export
Event
Callback
ให้ถูก Context
㉖ Export Name ต้องตรง
ถ้า Resource B มี
exports(
'GetPlayerData',
function(source)
-- ...
end
)
แต่ Resource A เรียก
exports['my_core']
:GetPlayer(source)
ก็ผิด
Dependency ไม่สามารถแก้ชื่อ API ที่ไม่ตรงกันได้
㉗ Resource Name ต้องตรงด้วย
Folder
my_core
แต่เรียก
exports['my-core']
:GetPlayer(...)
ถือเป็นคนละชื่อ
Resource Name มีผลกับ
Exports
Dependencies
ensure
restart
จึงไม่ควร Rename โดยไม่ตรวจ References
㉘ Dependency ประกาศด้วยชื่อ Resource จริง
ถ้า Folder Resource คือ
oxmysql
ใช้
dependency 'oxmysql'
ไม่ใช่ชื่อ Package ที่เดาเอง
เช่น
dependency 'mysql'
ถ้าไม่มี Resource ชื่อนั้นจริง
㉙ Framework Dependency ตัวอย่าง
Resource สำหรับ ESX อาจมี
dependency 'es_extended'
QBCore Resource อาจมี
dependency 'qb-core'
Qbox Resource อาจมี Dependency ตาม Resource ที่ Architecture นั้นใช้
ต้องตรวจชื่อ Resource และ Version จริง
อย่าเดาชื่อจากชื่อ Framework อย่างเดียว
㉚ Resource รองรับหลาย Framework ทำอย่างไร
ถ้า Resource สามารถทำงานกับ
ESX
หรือ
QBCore
หรือ
Qbox
ไม่ควรประกาศทั้งสามเป็น Mandatory Dependency หากไม่ได้ต้องใช้พร้อมกัน
เพราะจะกลายเป็น
ต้องติดตั้ง ESX
+
QBCore
+
Qbox
พร้อมกัน
ซึ่งไม่ใช่ Requirement จริง
㉛ Optional Dependency คืออะไร
บาง Integration เป็น Optional
เช่น
Resource ทำงาน Standalone ได้
แต่ถ้ามี target resource
→ เปิด Target Integration
กรณีนี้ไม่ควรประกาศ Resource นั้นเป็น Mandatory dependency หาก Resource สามารถทำงานได้โดยไม่มีมันจริง ๆ
ควร Detection/Bridge ตาม Architecture แทน
㉜ Mandatory กับ Optional Dependency ต้องแยก
ตัวอย่าง
oxmysql
→ จำเป็น
แต่
some_target
→ ไม่มีก็ใช้ Marker แทน
Manifest ควรมี
dependency 'oxmysql'
แต่ some_target อาจไม่ควรเป็น Mandatory Dependency
นี่ทำให้ Resource Flexible กว่า
㉝ Dependency Runtime Constraints คืออะไร
FiveM ไม่ได้จำกัด dependency ไว้แค่ชื่อ Resource
เอกสาร Cfx.re ปัจจุบันรองรับ Runtime Constraints เช่น
dependencies {
'/server:4500',
'/onesync',
'/gameBuild:h4',
'/native:0xE27C97A0'
}
แต่ละรายการตรวจ Environment ที่ Resource ต้องการ
㉞ /onesync คืออะไร
เขียน
dependency '/onesync'
หมายความว่า Resource ต้องการให้
State Awareness
ไม่ถูก Disable
เหมาะกับ Resource ที่พึ่ง OneSync Features
เช่น
Routing Buckets
Server-side Entity State
State Bags
OneSync-specific APIs
㉟ /onesync เปิด OneSync หรือไม่
ไม่
มันเป็น
Runtime Requirement
ไม่ใช่
Server Configuration Command
Server ต้อง Configure OneSync เอง
Manifest เพียงบอกว่า Resource นี้ต้องการ Environment แบบนั้น
㊱ /server:4500 คืออะไร
ตัวอย่าง
dependency '/server:4500'
หมายความว่า
FXServer Build
ต้อง >= 4500
ใช้เมื่อตัว Resource ต้องการ Feature หรือ Native ที่ต้องมี Server Build ขั้นต่ำ
㊲ ทำไม Minimum Server Build มีประโยชน์
แทนให้ Resource Start แล้วเจอ
attempt to call missing native
ภายหลัง
Developer สามารถกำหนด Requirement ตั้งแต่ Manifest
Concept คือ
Server เก่าเกินไป
↓
Requirement ไม่ผ่าน
↓
Resource ไม่ควรเริ่มแบบ Environment ผิด
㊳ /gameBuild คืออะไร
ตัวอย่าง
dependency '/gameBuild:h4'
เอกสาร Cfx.re ระบุว่า Constraint นี้ต้องการ Game Build อย่างน้อยตามค่าที่ระบุ
เหมาะกับ Resource ที่ใช้ Content จาก Game Build ใหม่
เช่น
Vehicles
Peds
DLC Assets
Specific Game Data
㊴ /native คืออะไร
สามารถ Require Server Native โดยตรง
เช่น
dependency '/native:0xE27C97A0'
หมายถึง Resource ต้องการให้ Server รองรับ Native Hash ดังกล่าว
ช่วยระบุ Feature Requirement ได้ละเอียดกว่าแค่ Server Version ในบางกรณี
㊵ /policy คืออะไร
Resource Manifest ยังรองรับ Policy Constraint
ตัวอย่างใน Documentation
dependency '/policy:subdir_file_mapping'
หมายถึง Server Key ต้องได้รับ Policy ที่เกี่ยวข้อง
ใช้กับ Feature ที่อยู่ภายใต้ Server Policy/Entitlement ที่กำหนด
ไม่ควร Copy Constraint นี้มาถ้า Resource ไม่ได้ใช้ Feature นั้น
㊶ ตัวอย่าง Manifest ที่มี Runtime Constraints
fx_version 'cerulean'
game 'gta5'
dependencies {
'/onesync',
'/server:4500',
'oxmysql'
}
server_script 'server.lua'
แปลว่า Resource ต้องการ
OneSync State Awareness
+
Server Build อย่างน้อย 4500
+
oxmysql Resource
ครบตาม Requirements
㊷ Dependency กับ Version ของ Resource อื่น
FiveM dependency 'resource_name' พื้นฐานบอกว่า Resource นั้นต้องมี/Load ก่อน
แต่ไม่ได้หมายความว่า
ต้องเป็น ox_lib 3.30.0
โดยอัตโนมัติ
ถ้า Resource ต้องการ API Version เฉพาะ Developer ต้องออกแบบ Version Check เพิ่มเองตาม Library
㊸ อย่าคิดว่า Resource Name เท่ากับ API Compatibility
มี Resource ชื่อ
my_core
อยู่จริง
ไม่ได้แปลว่า API Version ตรงกับ Script
เช่น Resource A ต้องการ
GetPlayerDataV2
แต่ Core รุ่นเก่ามีแค่
GetPlayerData
Dependency สามารถอยู่ครบแต่ Application ยัง Error ได้
㊹ Resource Lifecycle กับ Dependency
Resources สามารถ
Start
Stop
Restart
ได้แยกจากกัน
เมื่อ Dependency หยุด Resource ที่พึ่งมันอาจไม่สามารถใช้ API/Export นั้นได้ตามปกติอีก
ดังนั้น Production Server ต้องระวังการ Restart Core Libraries
㊺ ทำไม Restart Core Resource ต้องระวัง
สมมติ
oxmysql
↓
ใช้โดย
↓
20 Resources
ถ้า Restart Database Resource กลางในช่วง Server กำลังทำงาน Resources จำนวนมากอาจได้รับผลกระทบต่อ Operations ที่กำลังเกิดขึ้น
เช่น
Query
Callback
Transaction
Initialization
จึงไม่ควร Restart Critical Dependency โดยไม่เข้าใจ Impact
㊻ onResourceStart ใช้ทำอะไรกับ Dependency
FiveM มี Event
AddEventHandler(
'onResourceStart',
function(resourceName)
print(
resourceName,
'started'
)
end
)
สามารถใช้ Observe Resource Lifecycle
แต่ไม่ควรใช้เป็นข้ออ้างให้ละเลย Manifest Dependency
Lifecycle Event เหมาะกับ Runtime Reaction มากกว่า Declarative Requirement
㊼ onResourceStop ใช้ทำอะไร
สามารถตรวจเมื่อ Resource หยุด
AddEventHandler(
'onResourceStop',
function(resourceName)
print(
resourceName,
'stopped'
)
end
)
Resource ขั้นสูงอาจใช้เพื่อล้าง Integration State เมื่อ Dependency หรือ Resource ตัวเองหยุด
㊽ ต้องฟังทุก Resource Start ไหม
ไม่
ถ้าต้องการเฉพาะ Resource หนึ่ง
AddEventHandler(
'onResourceStart',
function(resourceName)
if resourceName
~= 'my_core' then
return
end
-- dependency started
end
)
แต่ Use Case นี้ควรมีเหตุผลจริง เช่น Optional Integration หรือ Runtime Reinitialization
㊾ Manifest Dependency ยังควรใช้แม้มี Lifecycle Events ไหม
ถ้า Dependency เป็น Mandatory ควรใช้
dependency 'my_core'
Lifecycle Event ไม่ได้แทน Declaration นี้
จำง่าย ๆ
dependency
→ Requirement
onResourceStart
→ Runtime Event
㊿ start, ensure และ dependency เกี่ยวกันอย่างไร
Server Commands มี Behavior ต่างกัน
start resource
→ Start Resource ถ้า Stopped
ensure resource
→ Start ถ้ายังไม่ทำงาน
→ Restart ถ้ากำลังทำงาน
dependency
→ กำหนด Resource Requirement/Load Relationship
อย่าใช้คำเหล่านี้แทนกัน
51 refresh เกี่ยวกับ Dependency อย่างไร
ถ้าเพิ่งเพิ่ม Dependency ใหม่เข้า resources/ ระหว่าง Server กำลังทำงาน
เช่น Copy
oxmysql/
เข้ามา
Server อาจต้อง
refresh
เพื่อ Rescan Resource Manifests
จากนั้นจึง
ensure oxmysql
ensure my_resource
ตามต้องการ
52 Missing Dependency แก้อย่างไร
ตรวจลำดับ
① Dependency Folder มีจริงไหม?
② fxmanifest.lua มีไหม?
③ Resource Name ถูกไหม?
④ refresh แล้วหรือยัง?
⑤ Dependency Start ได้ไหม?
⑥ Dependency Console มี Error ไหม?
⑦ Main Resource ใช้ชื่อ Dependency ถูกไหม?
อย่าแก้ด้วยการลบ dependency ออกจาก Manifest เพียงเพื่อให้ Resource Start
ถ้า Resource ต้องการมันจริง Error จะกลับมาใน Runtime
53 Dependency Start ไม่ได้ต้องแก้อันไหนก่อน
แก้ Resource ล่างสุดก่อน
สมมติ
garage
↓
core
↓
oxmysql
แล้ว garage ไม่ Start
ตรวจ
oxmysql
ก่อน
ถ้า Database Dependency พัง Core อาจพังตาม และ Garage ก็พังต่อ
นี่เป็นวิธี Debug Dependency Chain ที่เร็วกว่าไล่จาก Error ชั้นบนอย่างเดียว
54 No such export Debug อย่างไร
ใช้ Flow
No such export
↓
Resource Name ถูก?
↓
Resource Started?
↓
Export มีจริง?
↓
Client/Server Context ถูก?
↓
API Version ถูก?
↓
เรียกหลัง Resource พร้อม?
ตัวอย่าง Error
No such export GetPlayer
in resource my_core
อย่ารีบเพิ่ม
Wait(5000)
ก่อนตรวจชื่อ GetPlayer จริงใน Core
55 Export Runtime ตัวอย่าง
Dependency Resource:
local function getVersion()
return '1.0.0'
end
exports(
'GetVersion',
getVersion
)
Consumer:
local version =
exports['my_core']
:GetVersion()
print(version)
Manifest Consumer:
dependency 'my_core'
ทำให้ Relationship อ่านได้ชัดเจน
56 ตัวอย่าง Database Dependency
โครงสร้าง
oxmysql
↓
my_garage
my_garage/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
dependency 'oxmysql'
server_scripts {
'server/database.lua',
'server/main.lua'
}
server.cfg
ensure oxmysql
ensure my_garage
ตอนเปิด Server Architecture จึงเข้าใจง่าย
57 ตัวอย่าง Core + Database + Feature
oxmysql
↓
my_core
↓
my_inventory
↓
my_shops
Manifest my_core
dependency 'oxmysql'
Manifest my_inventory
dependency 'my_core'
Manifest my_shops
dependency 'my_inventory'
นี่เป็น Dependency Chain ที่ชัด
แต่ต้องคอยดูว่า Chain ยาวเกินความจำเป็นหรือไม่
58 ตัวอย่าง Resource ที่ใช้หลาย Dependencies
fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
author 'comsiam'
description 'FiveM garage system'
version '1.0.0'
dependencies {
'/onesync',
'ox_lib',
'oxmysql',
'my_core'
}
shared_script 'shared/config.lua'
client_scripts {
'client/main.lua',
'client/ui.lua'
}
server_scripts {
'server/database.lua',
'server/main.lua'
}
Requirement คือ
State Awareness
+
ox_lib
+
oxmysql
+
my_core
ก่อน Garage สามารถทำงานตาม Architecture ที่ออกแบบไว้
59 Checklist FiveM Resource Dependency
ก่อนเปิด Production ตรวจ
① Resource พึ่งอะไรจริง?
② Mandatory กับ Optional แยกแล้วหรือยัง?
③ dependency อยู่ใน fxmanifest.lua หรือไม่?
④ dependencies หลายตัวเขียนถูกหรือไม่?
⑤ Resource Name ตรง Folder หรือไม่?
⑥ Dependency มี fxmanifest.lua หรือไม่?
⑦ Dependency Start ได้จริงหรือไม่?
⑧ server.cfg จัด Order อ่านง่ายหรือไม่?
⑨ มี Wait ใช้แก้ Dependency หรือไม่?
⑩ มี Circular Dependency หรือไม่?
⑪ Dependency Chain ยาวเกินไปหรือไม่?
⑫ Export Name ถูกหรือไม่?
⑬ Client Export กับ Server Export แยกถูกหรือไม่?
⑭ Resource Version/API Compatible หรือไม่?
⑮ Resource ต้อง OneSync หรือไม่?
⑯ ถ้าต้อง ใช้ /onesync หรือยัง?
⑰ ต้อง Minimum Server Build หรือไม่?
⑱ ต้อง Game Build หรือไม่?
⑲ ต้อง Native Constraint หรือไม่?
⑳ มี Constraint ที่ Copy มาโดยไม่ใช้หรือไม่?
㉑ Restart Dependency แล้ว Consumer จะเกิดอะไร?
㉒ Resource Start/Stop Lifecycle รองรับหรือไม่?
㉓ No such export ถูก Debug จาก Root Cause หรือไม่?
㉔ เพิ่ม Resource ใหม่แล้ว refresh หรือยัง?
㉕ Critical Dependency ถูก Restart บน Production โดยไม่จำเป็นหรือไม่?
⑥⓪ ตัวอย่าง Dependency Architecture สำหรับ Production
สมมติ Server มี
Database
Core
Inventory
Garage
Shops
Jobs
สามารถออกแบบ
oxmysql
│
my_core
/ \
/ \
my_inventory my_garage
│
my_shops
my_core/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
dependency 'oxmysql'
server_script 'server/main.lua'
my_inventory/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
dependency 'my_core'
shared_script 'shared/config.lua'
client_script 'client/main.lua'
server_script 'server/main.lua'
my_garage/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
dependencies {
'/onesync',
'oxmysql',
'my_core'
}
shared_script 'shared/config.lua'
client_script 'client/main.lua'
server_scripts {
'server/database.lua',
'server/main.lua'
}
my_shops/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
dependencies {
'my_core',
'my_inventory'
}
client_script 'client/main.lua'
server_script 'server/main.lua'
server.cfg
# Database / Libraries
ensure oxmysql
# Core
ensure my_core
# Systems
ensure my_inventory
ensure my_garage
# Features
ensure my_shops
Architecture นี้ทำให้
Dependency Direction
เห็นได้ชัด
และลดปัญหา Resource เรียก API จากระบบที่ยังไม่พร้อม
Resource Dependency ที่ดีควรเป็นทิศทางเดียว
พยายามออกแบบ
Low-level
↓
High-level
เช่น
Database
↓
Core
↓
Inventory
↓
Shop
หลีกเลี่ยง
Core
↓
Inventory
↓
Shop
↓
Core
เพราะจะกลายเป็น Circular Dependency และทำให้ Resource Coupling สูงมาก
Dependency ไม่ควรทำให้ทุก Resource รู้จักกันหมด
Architecture ที่ไม่ดี
garage
→ inventory
→ phone
→ housing
→ police
→ mechanic
→ banking
เพียงเพื่อทำงาน Feature เล็ก ๆ
ควรพิจารณา
Core APIs
Events
Interfaces
Bridge Layer
เพื่อลด Direct Coupling
Optional Integration ควรแยกจาก Core Logic
สมมติ Garage รองรับ Target System แต่ไม่ได้บังคับ
Architecture ควรเป็น
Garage Core
↓
Target Adapter
ถ้า Target ไม่มี
Garage Core
ยังทำงาน
ไม่ควรประกาศ Target เป็น Mandatory Dependency ถ้าจริง ๆ แล้วมี Alternative Interaction
อย่าปิด Error ด้วยการลบ Dependency
หาก Resource แจ้งว่า Dependency หาย
วิธีที่ผิดคือ
ลบ dependency จาก fxmanifest
↓
Resource Start ผ่าน
แต่ Code ข้างในยังเรียก
exports['missing_resource']
สุดท้ายก็จะพังตอนใช้งาน
Dependency Error ที่เกิดเร็วกลับมีประโยชน์ เพราะมันบอกปัญหาก่อน Player เข้าใช้งาน Feature จริง
คำถามที่พบบ่อยเกี่ยวกับ FiveM Resource Dependency
FiveM Resource Dependency คืออะไร
คือ Requirement ที่กำหนดว่า Resource ปัจจุบันต้องพึ่ง Resource หรือ Runtime Environment อื่นก่อนทำงาน
เขียน Dependency อย่างไร
dependency 'my_core'
หลาย Dependency เขียนอย่างไร
dependencies {
'ox_lib',
'oxmysql',
'my_core'
}
Dependency มีไว้จัด Start Order อย่างเดียวไหม
ไม่ ยังเป็นการประกาศ Requirement ของ Resource ให้ Resource Manager และ Developer ทราบด้วย
ต้องเรียง server.cfg อีกไหม
การจัด server.cfg เป็น Layer ที่อ่านง่ายยังเป็นแนวทางที่ดี แม้ Manifest จะประกาศ Dependency ไว้แล้ว
ใช้ Wait รอ Dependency ได้ไหม
ไม่ควรใช้เป็นวิธีแก้หลัก ควรประกาศ Dependency และออกแบบ Initialization ให้ถูกต้อง
dependency เปิด Resource นั้นไหม
ตาม Resource Manifest ระบบใช้ Dependency เพื่อกำหนดว่า Resource ที่ระบุต้อง Load ก่อน Resource ปัจจุบัน แต่ Server Configuration ก็ควรระบุ Resources ที่ Serverต้องใช้อย่างชัดเจนด้วย
/onesync คืออะไร
Runtime Constraint ที่ระบุว่า State Awareness ต้องไม่ถูก Disable
/onesync เปิด OneSync ไหม
ไม่
Minimum Server Build เขียนอย่างไร
ตัวอย่าง
dependency '/server:4500'
Game Build Requirement เขียนอย่างไร
ตัวอย่าง
dependency '/gameBuild:h4'
Require Native ได้ไหม
ได้ผ่าน /native:<hash> ตาม Resource Manifest Runtime Constraints
No such export เกิดจาก Dependency เสมอไหม
ไม่ อาจเกิดจาก Resource Name ผิด, Export Name ผิด, Resource ไม่ได้ Start, Client/Server Context ผิด หรือ API Version ไม่ตรง
Export Client เรียกจาก Server ได้ไหม
ไม่ควรคิดว่า Client และ Server Exports เป็นระบบเดียวกัน ทั้งสองเป็นคนละ Runtime Context
Resource A พึ่ง B และ B พึ่ง A ได้ไหม
เป็น Circular Dependency ซึ่งควรหลีกเลี่ยงและ Refactor Architecture
Optional Resource ควรใส่ dependency ไหม
ถ้า Resource หลักสามารถทำงานได้โดยไม่มี Integration นั้นจริง ๆ ไม่ควรทำให้มันเป็น Mandatory Dependency โดยไม่จำเป็น
Dependency Resource Restart ได้ไหม
ได้ แต่ Consumer Resources ที่ใช้งาน API ของ Dependency นั้นอาจได้รับผลกระทบ จึงต้องระวังบน Production
Resource ใหม่เพิ่ง Copy เข้า Server ต้องทำอะไร
หาก Server กำลังทำงาน ใช้
refresh
เพื่อ Rescan Resources แล้วจึง Start/Ensure ตามต้องการ
ensure คืออะไร
ถ้า Resource ยังไม่ Start จะ Start และถ้ากำลังทำงานอยู่จะ Restart
start ต่างจาก ensure อย่างไร
start จะ Start Resource หาก Stopped ส่วน ensure จะทำให้ Resource อยู่ในสถานะ Started และ Restart หากกำลังทำงานอยู่
Dependency Resource ไม่มี fxmanifest.lua ทำอย่างไร
ต้องแก้ Resource นั้นก่อน เพราะ Resource ที่ FiveM Parse อย่างถูกต้องต้องมี Resource Manifest
Framework รองรับหลายตัวควรใส่ทุก Framework ใน dependencies ไหม
ไม่ ถ้าเลือกใช้เพียง Framework เดียวในแต่ละ Server การบังคับทุก Framework พร้อมกันเป็น Architecture ที่ผิด Requirement
สรุป FiveM Resource Dependency คืออะไร
FiveM Resource Dependency คือระบบที่ใช้ประกาศว่า Resource หนึ่งต้องการ Resource หรือ Runtime Requirement ใดก่อนจึงจะสามารถทำงานได้อย่างถูกต้อง
Dependency ตัวเดียว
dependency 'oxmysql'
หลายตัว
dependencies {
'ox_lib',
'oxmysql',
'my_core'
}
และ FiveM ยังรองรับ Runtime Constraints เช่น
dependencies {
'/onesync',
'/server:4500',
'/gameBuild:h4'
}
สิ่งสำคัญคือต้องแยก
Resource Dependency
→ Resource ที่ต้องใช้
ออกจาก
Runtime Constraint
→ Environment ที่ต้องมี
และแยกจาก
server.cfg
→ Resources ที่ Server จะ Start/Ensure
ด้วย
ปัญหาอย่าง
No such export
ไม่ได้หมายความว่า “ต้องเพิ่ม Wait”
แต่ควรตรวจ
Resource Name
↓
Resource State
↓
Dependency
↓
Export Name
↓
Client/Server Context
↓
API Version
ตามลำดับ
Resource Architecture ที่ดีควรมี Dependency Direction ชัดเจน เช่น
Database
↓
Core
↓
Feature
ไม่ใช่ทุก Resource พึ่งกันไปมาจนเกิด
Circular Dependency
สำหรับ Developer ที่เรียน FiveM กับ comsiam วิธีคิดที่ควรใช้คือ ถ้า Resource ไม่สามารถทำงานโดยไม่มี Resource อื่นจริง ๆ ให้ประกาศ Dependency อย่างชัดเจน ไม่ควรซ่อน Requirement ไว้ใน Code แล้วหวังว่า Admin จะเดา Start Order ถูก
และหลักจาก comsiam คือ Dependency ที่ดีที่สุดไม่ใช่ Resource ที่มี Dependencies เยอะที่สุด แต่เป็น Resource ที่ประกาศเฉพาะสิ่งที่จำเป็น และมีทิศทางการพึ่งพาที่เรียบง่ายจนเปิด fxmanifest.lua แล้วเข้าใจ Architecture ได้ทันที
หัวข้อถัดไปคือ FiveM start, ensure, restart และ stop ต่างกันอย่างไร ซึ่งจะต่อจาก Dependency โดยตรง และอธิบาย Resource Commands ทั้ง 4 ตัวว่าแต่ละคำสั่งทำอะไร ควรใช้ตอนไหน และทำไม ensure ไม่ได้มีความหมายเหมือน start ทุกกรณี
Comments
Post a Comment