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

Popular posts from this blog

FiveM ยังน่าเล่นไหม? Enhanced เปลี่ยน FiveM แค่ไหน

FiveM คืออะไร เล่นอย่างไร สำหรับมือใหม่ เริ่มต้นตั้งแต่ศูนย์

วิธีตั้ง Admin Permission ด้วย add_ace และ add_principal FiveM แบบละเอียด