FiveM Routing Bucket คืออะไร? วิธีสร้าง Instance แยกผู้เล่นและ Entity อย่างถูกต้อง

 FiveM Routing Bucket คือระบบสำหรับแยก Players และ Networked Entities ออกเป็นคนละ Game State หรือ Instance ภายใน Server เดียวกัน คล้ายแนวคิด Dimension / Virtual World โดยผู้เล่นที่อยู่คนละ Routing Bucket จะไม่เห็น Players และ Entities ของอีก Bucket ตามระบบ Routing ของ OneSync.

Routing Bucket เหมาะมากกับระบบประเภท Character Selection, Party/Session, Multi-mode Server และ Instance Gameplay แต่ Cfx.re ระบุชัดว่า ไม่ควรใช้ Routing Bucket เป็นวิธีหลักสำหรับ Interiors เพราะ Interior มีแนวทาง Scoped/Conceal ที่เหมาะกว่า.

Meta SEO

Meta Title: FiveM Routing Bucket คืออะไร? วิธีสร้าง Instance แยก Player และ Entity

Meta Description: อธิบาย FiveM Routing Bucket แบบละเอียด วิธีใช้ SetPlayerRoutingBucket, SetEntityRoutingBucket, Population, Entity Lockdown และแก้ปัญหา Player หรือ Vehicle หายหลังเปลี่ยน Bucket

Focus Keyword: FiveM Routing Bucket

Related Keywords: FiveM Instance, FiveM Dimension, SetPlayerRoutingBucket, SetEntityRoutingBucket, FiveM OneSync, Routing Bucket FiveM

สารบัญ

① FiveM Routing Bucket คืออะไร

Routing Bucket คือระบบ Instance ของ FiveM

แนวคิด:

FiveM Server

Bucket 0
├── Player A
├── Player B
└── Vehicle A

Bucket 10
├── Player C
├── Player D
└── Vehicle B

Bucket 20
├── Player E
└── Vehicle C

Player ใน Bucket 10 จะอยู่ใน Game State แยกจาก Player ใน Bucket 0 หรือ 20

Cfx.re ระบุว่าสามารถ Assign ทั้ง Player และ Entity ไปยัง Routing Bucket และแต่ละฝ่ายจะมองเห็น Players/Entities ที่อยู่ใน Bucket เดียวกัน.

② Routing Bucket เหมือน Dimension หรือไม่

แนวคิดใกล้เคียงกันมาก

Cfx.re ระบุว่า Routing Buckets เป็นระบบ Dimension ของ FiveM และสามารถเทียบได้กับ Dimension หรือ Instance System จากแพลตฟอร์ม Multiplayer อื่น แม้รายละเอียดการทำงานภายในจะแตกต่างกัน.

จำง่ายๆ:

Routing Bucket
≈ Dimension
≈ Virtual World
≈ Instance

แต่ควรใช้คำว่า Routing Bucket เมื่อเขียน Resource FiveM ปัจจุบัน

③ Routing Bucket ทำงานอย่างไร

หลักคือ:

Player Bucket
+
Entity Bucket
=
Visibility

ถ้า Player และ Vehicle อยู่ Bucket เดียวกัน Player สามารถมองเห็น Entity นั้นตาม Scope และ Networking ปกติ

แต่ถ้าอยู่คนละ Bucket Entity อาจไม่ปรากฏให้ Client คนนั้นเห็นเลย.

④ Routing Bucket เกี่ยวกับ OneSync หรือไม่

เกี่ยวข้องโดยตรง

Routing Buckets เป็นส่วนหนึ่งของระบบ OneSync และ Cfx.re ระบุ Native สำหรับจัดการ Player, Entity, Population และ Lockdown ของแต่ละ Bucket ภายใน OneSync Documentation.

Resource ที่ใช้ Routing Buckets จึงควรออกแบบตาม OneSync Networking ไม่ใช่แนวทาง Client-only แบบเก่า

⑤ แต่ละ Bucket มี World Grid แยกกันหรือไม่

Cfx.re ระบุว่าแต่ละ Routing Bucket มี World Grid ของตัวเองสำหรับ Population Owners.

ดังนั้น Bucket ไม่ได้เป็นเพียง Filter ว่าใครเห็นใคร แต่ยังมี Behavior ระดับ World/Population ที่แยกจาก Bucket อื่นด้วย

⑥ Bucket 0 คืออะไร

โดยทั่วไป Bucket 0 สามารถมองเป็น Main/Default World ของ Server

ตัวอย่าง:

Bucket 0
= Gameplay หลัก

Bucket 100
= Character Selection

Bucket 200
= Party Instance

เมื่อระบบ Instance จบ มักย้าย Player กลับ:

SetPlayerRoutingBucket(source, 0)

อย่าให้ Player ค้างอยู่ Instance เก่าโดยไม่ตั้งใจ

⑦ Bucket ID ต้องเป็นเลขหรือไม่

Routing Bucket ใช้ Bucket ID เป็น Integer

ตัวอย่าง:

SetPlayerRoutingBucket(source, 10)

Cfx.re มี Native SET_PLAYER_ROUTING_BUCKET สำหรับกำหนด Bucket ของ Player และ SET_ENTITY_ROUTING_BUCKET สำหรับ Entity.

⑧ ควรใช้ Bucket ID แบบไหน

ควรสร้าง Convention ของ Server เช่น:

0       = Main World
100-199 = Character Instances
200-299 = Party Sessions
300-399 = Game Modes

หรือใช้ Dynamic Bucket Allocator

เป้าหมายคือไม่ให้ Resource หลายตัวเลือก Bucket ID ชนกันโดยไม่รู้ตัว

⑨ ย้าย Player เข้า Routing Bucket อย่างไร

ใช้:

SetPlayerRoutingBucket(source, bucketId)

ตัวอย่าง:

local bucketId = 100

SetPlayerRoutingBucket(
    source,
    bucketId
)

Cfx.re มี Native สำหรับกำหนด Routing Bucket ของ Player โดยตรง และ OneSync Documentation ใช้ Native นี้ในตัวอย่าง Entity Lockdown.

⑩ ย้าย Player กลับโลกหลักอย่างไร

ใช้:

SetPlayerRoutingBucket(source, 0)

ตัวอย่าง:

RegisterNetEvent(
    'instance:leave',
    function()
        local src = source

        SetPlayerRoutingBucket(
            src,
            0
        )
    end
)

สำหรับ Production Resource ต้องตรวจว่า Player มีสิทธิ์ออก Instance ณ จุดนั้นหรือไม่

⑪ อย่าให้ Client กำหนด Bucket ID เองโดยตรง

ตัวอย่างที่ควรหลีกเลี่ยง:

TriggerServerEvent(
    'instance:setBucket',
    999999
)

แล้ว Server นำเลขที่ Client ส่งมาใช้ทันที

ควรเป็น:

Client ขอเข้า Session
↓
Server ตรวจ Session
↓
Server หา Bucket ID
↓
Server ย้าย Player

เพราะ Bucket Assignment เป็น Server Gameplay State ที่ควรถูกควบคุมจาก Server

⑫ Server ควรเป็นผู้เลือก Bucket

ตัวอย่าง:

RegisterNetEvent(
    'party:joinInstance',
    function(partyId)
        local src = source

        local bucket =
            GetBucketForParty(partyId)

        if not bucket then
            return
        end

        SetPlayerRoutingBucket(
            src,
            bucket
        )
    end
)

GetBucketForParty() เป็น Function สมมติ

หลักคือ Client ส่ง Request แต่ Server เป็นผู้ตัดสิน Instance

⑬ Entity ก็มี Routing Bucket ได้

ใช่

Cfx.re รองรับ:

SetEntityRoutingBucket(
    entity,
    bucketId
)

และระบุว่า Player กับ Entity ที่อยู่ Bucket เดียวกันสามารถถูก Route ให้อยู่ใน Game State เดียวกัน.

⑭ Player เข้า Instance แต่ Vehicle หายเพราะอะไร

สาเหตุที่พบบ่อยคือ:

Player Bucket = 10

Vehicle Bucket = 0

Player ถูกย้ายออกจากโลกหลัก แต่ Vehicle ไม่ได้ย้ายตาม

แก้โดยจัด Entity ที่ต้องอยู่ใน Instance ให้ Bucket ตรงกับ Player

SetEntityRoutingBucket(
    vehicle,
    10
)

⑮ ตัวอย่างย้าย Player และ Vehicle พร้อมกัน

local bucketId = 10

SetPlayerRoutingBucket(
    source,
    bucketId
)

SetEntityRoutingBucket(
    vehicle,
    bucketId
)

นี่เป็น Pattern เดียวกับตัวอย่าง OneSync ของ Cfx.re ที่ย้าย Player และ Vehicle ไป Bucket เดียวกัน.

⑯ Ped และ Object ใช้ Bucket ได้ไหม

Routing Bucket ทำงานกับ Networked Entities ไม่ได้จำกัดเฉพาะ Vehicle

OneSync Documentation กล่าวถึง Player หรือ Entity โดยทั่วไป และรองรับ Server-created Peds, Vehicles และ Objects ภายในระบบ Entity Synchronization.

⑰ Entity สร้างหลัง Player เข้า Bucket ควรทำอย่างไร

Resource ควรรู้ว่า Entity นั้นเป็นของ Session ไหน

ตัวอย่าง:

Create Entity
↓
หา Session Bucket
↓
SetEntityRoutingBucket
↓
Set State ที่จำเป็น

ไม่ควรสร้าง Entity แล้วปล่อยไว้ Bucket 0 หาก Intended Gameplay อยู่ใน Instance อื่น

⑱ ตรวจว่า Player อยู่ Bucket ไหนอย่างไร

FiveM มี:

GetPlayerRoutingBucket(source)

Native นี้คืน Routing Bucket ปัจจุบันของ Player.

ตัวอย่าง:

local bucket =
    GetPlayerRoutingBucket(source)

print(
    ('Player bucket: %s')
    :format(bucket)
)

⑲ ตรวจ Entity Bucket อย่างไร

ใช้:

GetEntityRoutingBucket(entity)

Cfx.re มี Native สำหรับอ่าน Bucket ของ Entity.

ตัวอย่าง:

local bucket =
    GetEntityRoutingBucket(vehicle)

print(
    ('Vehicle bucket: %s')
    :format(bucket)
)

⑳ Debug Player ไม่เห็น Entity ให้เทียบสองค่า

ใช้:

local playerBucket =
    GetPlayerRoutingBucket(source)

local entityBucket =
    GetEntityRoutingBucket(entity)

แล้วตรวจ:

Player Bucket == Entity Bucket ?

ถ้าไม่เท่ากัน นี่เป็นจุดแรกที่ควรแก้ก่อน Debug Network ID หรือ Entity Ownership ต่อ

㉑ Routing Bucket ใช้ทำ Character Selection ได้ไหม

ได้ และเป็น Use Case ที่ Cfx.re ระบุโดยตรง

Cfx.re ยกตัวอย่าง Character Screen ที่ถูก Instance แยกจาก Gameplay เป็นหนึ่งใน Use Cases ของ Routing Buckets.

Flow:

Player Connecting
↓
Player Joining
↓
ย้ายเข้า Character Bucket
↓
เลือก Character
↓
โหลดข้อมูลเสร็จ
↓
ย้ายกลับ Bucket 0

㉒ ทำ Character Bucket ต่อ Player หรือรวมกันดี

ขึ้นกับ UI และ Gameplay

Shared Character Bucket

ผู้เล่นหลายคนอยู่ Instance เดียวกัน

Private Character Bucket

หนึ่ง Player ต่อหนึ่ง Bucket

หากต้องการให้ Character Screen เป็น Private ควรมี Bucket Allocator ที่สร้าง/คืน Bucket IDs อย่างเป็นระบบ

㉓ Private Instance ควร Cleanup เมื่อ Player ออก

ถ้า Player Disconnect ขณะอยู่ Bucket 125

Resource ควร Cleanup:

Session Mapping
Temporary Entities
Bucket Allocation
Temporary State

โดยใช้ playerDropped หรือ Lifecycle ที่เหมาะสม

ไม่ควรปล่อย Session Table เก่าค้างอยู่

㉔ Routing Bucket ใช้ทำ Party หรือ Session ได้ไหม

ได้

Cfx.re ระบุ Session/Party Systems เป็น Use Case โดยตรง.

ตัวอย่าง:

Party A
→ Bucket 201

Party B
→ Bucket 202

Party C
→ Bucket 203

แต่ละ Party สามารถเล่นบนพิกัดเดียวกันโดยไม่เห็น Entity/Player ของ Party อื่น

㉕ Multi-mode Server ใช้ได้ไหม

ได้

Cfx.re ระบุ Multi-mode Servers เป็นอีก Use Case เช่นแต่ละ Game Mode ทำงานแยก Game State โดยไม่รบกวนกัน.

ตัวอย่าง:

Bucket 0 = Main Lobby
Bucket 10 = Mode A
Bucket 20 = Mode B
Bucket 30 = Mode C

㉖ Interiors ควรใช้ Routing Bucket ไหม

Cfx.re ระบุชัดว่า Interiors ไม่ใช่ Use Case ที่แนะนำสำหรับ Routing Buckets.

หากต้องการซ่อน/แยกพื้นที่ Interior ควรตรวจระบบ Conceal หรือ Scoped Routing ที่เหมาะสมมากกว่า

อย่าใช้ Bucket กับทุกห้องเพียงเพราะทำง่าย

㉗ ทำไม Interior ไม่เหมาะ

เพราะ Routing Bucket แยก Game State ทั้ง Bucket

แต่ Interior หลายกรณีต้องการเพียงการควบคุม Visibility ภายในพื้นที่หนึ่งโดยที่ Player ยังควรรับรู้สิ่งที่เกิดขึ้นนอกพื้นที่บางส่วน

Cfx.re จึงแยก Use Case นี้ออกจาก Routing Buckets.

㉘ แต่ละ Bucket มี Population แยกไหม

Cfx.re ระบุว่าแต่ละ Bucket มี World Grid ของตัวเองสำหรับ Population Owners และมี Native สำหรับเปิดหรือปิด Population ภายใน Bucket.

ใช้:

SetRoutingBucketPopulationEnabled(
    bucketId,
    false
)

㉙ ปิด Population เมื่อไหร่

เหมาะกับ Instance ที่ต้องการ Environment ควบคุมเอง เช่น:

Character Selection
Private Session
Controlled Game Mode

ตัวอย่าง Cfx.re:

SetRoutingBucketPopulationEnabled(
    1,
    false
)

เพื่อปิด Population ใน Bucket นั้น.

㉚ เปิด Population กลับอย่างไร

ใช้:

SetRoutingBucketPopulationEnabled(
    bucketId,
    true
)

ควรเลือกตาม Gameplay Design ไม่จำเป็นต้องปิด Population ทุก Bucket

㉛ Entity Lockdown คืออะไร

Routing Bucket สามารถมี Entity Lockdown Mode ของตัวเอง เพื่อกำหนดว่า Client สามารถสร้าง Entity ภายใน Bucket ได้มากน้อยแค่ไหน.

ใช้:

SetRoutingBucketEntityLockdownMode(
    bucketId,
    mode
)

㉜ Lockdown Mode มีอะไรบ้าง

Documentation ปัจจุบันของ Cfx.re ระบุ:

Modeความหมาย
fullปิด Dummy Object Creation เพิ่มเติม ใช้กับ FiveM for GTAV Enhanced
strictClient สร้าง Entity ไม่ได้
relaxedBlock Script-owned Entity ที่ Client สร้าง
inactiveClient สร้าง Entity ได้

㉝ strict เหมาะกับอะไร

strict เหมาะกับ Instance ที่ Server ต้องการควบคุม Entity Creation อย่างมาก

ตัวอย่าง:

SetRoutingBucketEntityLockdownMode(
    bucketId,
    'strict'
)

Cfx.re ระบุว่าใน Mode นี้ Clients ไม่สามารถสร้าง Entities ได้.

㉞ inactive คืออะไร

inactive คือ Mode ที่เปิดให้ Clients สามารถสร้าง Entities ได้

ถ้า Resource ไม่ต้องการ Lockdown Behavior สามารถใช้ Mode นี้ตาม Architecture ของ Server.

㉟ full ใช้ได้ทุก Server ไหม

ไม่

Cfx.re ระบุว่า full เป็น Lockdown Mode ที่ใช้เฉพาะ FiveM for GTAV Enhanced และเพิ่มการป้องกัน Dummy Object Creation.

Resource ที่ต้องรองรับทั้ง Legacy และ Enhanced ต้องตรวจ Environment ก่อนใช้

㊱ ตัวอย่าง Private Bucket แบบควบคุม Entity

local bucketId = 100

SetRoutingBucketEntityLockdownMode(
    bucketId,
    'strict'
)

SetRoutingBucketPopulationEnabled(
    bucketId,
    false
)

SetPlayerRoutingBucket(
    source,
    bucketId
)

โครงสร้างนี้ตรงกับแนวทางตัวอย่างของ OneSync Documentation: ตั้ง Lockdown → ปิด Population → ย้าย Player เข้า Bucket.

㊲ Strict Lockdown แล้ว Client Resource พัง

เป็นไปได้หาก Resource เดิมคาดหวังว่า Client จะสร้าง Networked Entity เอง

เมื่อใช้ strict Cfx.re ระบุว่า Client ไม่สามารถสร้าง Entities ใน Bucket นั้นได้.

จึงควรย้าย Entity Creation ที่สำคัญไป Server หรือปรับ Resource Architecture

㊳ Entity Lockdown กับ sv_stateBagStrictMode เหมือนกันไหม

ไม่

Entity Lockdown

ควบคุมการสร้าง Entity

sv_stateBagStrictMode

ควบคุมการแก้ Replicated State Bag

จึงเป็นคนละ Layer ของ OneSync Security/Authority

㊴ Network Event ข้าม Routing Bucket ได้ไหม

อย่าสมมติว่า Routing Bucket เป็น Security Boundary สำหรับ Custom Network Events ทั้งหมด

Bucket มีหน้าที่หลักด้าน Game State/Entity Routing

Resource ที่รับ Client Network Event ยังต้องตรวจเองว่า Player อยู่ Session/Bucket ที่ถูกต้องก่อนทำ Action

ตัวอย่าง:

local bucket =
    GetPlayerRoutingBucket(source)

if bucket ~= expectedBucket then
    return
end

㊵ Event ของ Instance ควรตรวจ Bucket

ตัวอย่าง:

RegisterNetEvent(
    'session:finish',
    function(sessionId)

        local src = source
        local session =
            Sessions[sessionId]

        if not session then
            return
        end

        local currentBucket =
            GetPlayerRoutingBucket(src)

        if currentBucket ~=
            session.bucket then
            return
        end

        -- ทำ Logic ต่อ
    end
)

Client ไม่ควรสามารถ Trigger Action ของ Session อื่นเพียงเพราะรู้ Event Name

㊶ Control Request ข้าม Bucket มีข้อจำกัด

Server Commands ปัจจุบันระบุว่าเมื่อเปิด sv_filterRequestControl ใน Mode ที่ไม่ใช่ Off จะมี Check เพิ่มเติม และ Control Request Events ไม่สามารถ Route ข้าม Routing Buckets.

นี่สำคัญมากเมื่อตรวจปัญหา Network Control หลังย้าย Player หรือ Entity เข้า Instance

㊷ strict Lockdown มีผลกับ Control Request ด้วย

Cfx.re ระบุว่าเมื่อใช้ sv_filterRequestControl Mode ที่ไม่ใช่ Off Control Request จะถูก Block หาก Sender อยู่ใน strict Entity Lockdown Mode.

ดังนั้นอาการ:

NetworkRequestControlOfEntity
ไม่สำเร็จ

อาจไม่ได้เกิดจาก Entity Ownership อย่างเดียว ต้องตรวจ Bucket Lockdown และ Server Control Policy ด้วย

㊸ Routing Bucket มีต้นทุน Memory หรือไม่

มี

Cfx.re ระบุว่า แต่ละ Routing Bucket มี Memory Cost และ Behavior ไม่ได้เหมือน Dimension System จากแพลตฟอร์มอื่นแบบหนึ่งต่อหนึ่ง.

ดังนั้นไม่ควรสร้าง Bucket ใหม่จำนวนมากแบบไม่มี Lifecycle Management

㊹ ไม่ควรสร้าง Bucket ใหม่ทุก Action

ตัวอย่างที่ไม่ดี:

Player เปิด Menu
→ สร้าง Bucket ใหม่

ปิด Menu
→ ไม่ Cleanup

เปิดใหม่
→ Bucket ใหม่อีก

ควรมี Bucket Allocator/Session Manager ที่ Reuse หรือ Cleanup Bucket IDs ตาม Architecture

㊺ Bucket ID หายเองไหม

Bucket ID เป็นค่าที่ Resource เลือกใช้ แต่ State/Entities/Players ภายในต้องถูกจัด Lifecycle เอง

Resource ควรเก็บ Mapping เช่น:

Sessions[sessionId] = {
    bucket = bucketId,
    players = {},
    entities = {}
}

แล้ว Cleanup เมื่อ Session สิ้นสุด

㊻ Player Disconnect ควรคืน Bucket หรือไม่

Player Connection หายไปเอง แต่ Resource ยังควร Cleanup Session Mapping

ใช้ playerDropped:

AddEventHandler(
    'playerDropped',
    function()
        local src = source

        RemovePlayerFromSession(src)
    end
)

เพื่อไม่ให้ข้อมูล Party/Instance เก่าค้างอยู่

㊼ Resource Restart ระหว่างมี Instances ทำอย่างไร

ต้องมี Recovery Strategy

เมื่อ Resource Restart:

Session Table ใน Memory
→ หาย

Players
→ อาจยังอยู่ใน Bucket ที่ตั้งไว้

จึงควรพิจารณา onResourceStop / onResourceStart และ Restore/Reset Players ตาม Architecture

อย่าคิดว่า Restart Resource แล้ว Instance State จะจัดตัวเองทั้งหมด

㊽ ควร Reset Players กลับ Bucket 0 เมื่อ Resource Stop ไหม

สำหรับ Resource ที่เป็นเจ้าของ Instance เหล่านั้น อาจเป็นแนวทางที่เหมาะสม

ตัวอย่างเชิงแนวคิด:

AddEventHandler(
    'onResourceStop',
    function(resourceName)

        if resourceName ~=
            GetCurrentResourceName() then
            return
        end

        -- Reset players ที่ resource นี้จัดการ
    end
)

แต่ต้องระวังไม่ย้าย Player ที่ถูก Resource อื่นจัดการอยู่

㊾ FiveM Routing Bucket Player ไม่เห็นกัน แก้อย่างไร

ตรวจ:

Player A Bucket = ?
Player B Bucket = ?

ด้วย:

GetPlayerRoutingBucket(playerId)

ถ้าอยู่คนละ Bucket การไม่เห็นกันสามารถเป็น Behavior ที่ถูกต้องของระบบ.

㊿ FiveM Routing Bucket Entity หาย แก้อย่างไร

ใช้ Checklist:

  1. Player Bucket เท่าไร

  2. Entity Bucket เท่าไร

  3. Entity ยัง Exist หรือไม่

  4. Entity มี Network ID หรือไม่

  5. Entity อยู่ใน Scope หรือไม่

  6. Resource ย้าย Player แต่ไม่ได้ย้าย Entityหรือไม่

  7. Entity ถูก Cleanup แล้วหรือไม่

  8. Routing Bucket ถูก Reset โดย Resource อื่นหรือไม่

เริ่มจากเปรียบเทียบ:

GetPlayerRoutingBucket(source)
GetEntityRoutingBucket(entity)

ก่อน Debug OneSync ขั้นลึก.

ตาราง Routing Bucket Functions สำคัญ

Nativeหน้าที่
SetPlayerRoutingBucketย้าย Player เข้า Bucket
GetPlayerRoutingBucketดู Bucket ของ Player
SetEntityRoutingBucketย้าย Entity เข้า Bucket
GetEntityRoutingBucketดู Bucket ของ Entity
SetRoutingBucketPopulationEnabledเปิด/ปิด Population
SetRoutingBucketEntityLockdownModeตั้ง Entity Lockdown

Native กลุ่มนี้ถูกรวมไว้ใน OneSync Routing Bucket Documentation ของ Cfx.re.

ตัวอย่างสร้าง Private Instance แบบพื้นฐาน

local nextBucket = 1000
local playerBuckets = {}

local function createPrivateBucket(src)
    local bucket = nextBucket
    nextBucket = nextBucket + 1

    playerBuckets[src] = bucket

    SetRoutingBucketEntityLockdownMode(
        bucket,
        'strict'
    )

    SetRoutingBucketPopulationEnabled(
        bucket,
        false
    )

    SetPlayerRoutingBucket(
        src,
        bucket
    )

    return bucket
end

นี่เป็น Architecture ตัวอย่างสำหรับอธิบายการจัด Bucket ไม่ใช่ระบบ Allocation Production ที่สมบูรณ์

ตัวอย่างออกจาก Private Instance

local function leavePrivateBucket(src)
    SetPlayerRoutingBucket(
        src,
        0
    )

    playerBuckets[src] = nil
end

หาก Instance มี Entities Resource ต้อง Cleanup หรือย้าย Entities เหล่านั้นด้วย

ตัวอย่าง Party Instance

local parties = {
    [25] = {
        bucket = 525,
        players = {}
    }
}

local function joinPartyInstance(
    src,
    partyId
)
    local party = parties[partyId]

    if not party then
        return false
    end

    SetPlayerRoutingBucket(
        src,
        party.bucket
    )

    party.players[src] = true

    return true
end

Server เป็นผู้เลือก Bucket จาก Party Data ไม่ใช่ให้ Clientกำหนด Bucket ID ตามใจ

ตัวอย่างย้าย Vehicle ตาม Player

local playerBucket =
    GetPlayerRoutingBucket(source)

SetEntityRoutingBucket(
    vehicle,
    playerBucket
)

เหมาะเมื่อ Vehicle ถูกสร้างมาเพื่อใช้งานเฉพาะ Session ของ Player นั้น

ตัวอย่าง Debug Bucket

RegisterCommand(
    'debugbucket',
    function(source)

        if source == 0 then
            return
        end

        local bucket =
            GetPlayerRoutingBucket(source)

        print((
            'Player %s is in bucket %s'
        ):format(
            source,
            bucket
        ))
    end,
    false
)

สำหรับ Production ควรจำกัด Debug Command ด้วย Permission ที่เหมาะสม

FiveM SetPlayerRoutingBucket ไม่ทำงาน

ตรวจ:

OneSync
↓
Server-side Script
↓
Player ID ถูก?
↓
Bucket ID ถูก?
↓
Script Error?
↓
Resource Running?

และใช้ GetPlayerRoutingBucket() หลัง Set เพื่อตรวจค่าที่ Server เห็นจริง.

FiveM SetEntityRoutingBucket ไม่ทำงาน

ตรวจว่า:

  • Entity มีอยู่จริง

  • Entity Handle ถูกต้องฝั่ง Server

  • Entity เป็น Networked Entity ตาม Use Case

  • Resource ไม่ได้ลบ Entity

  • Bucket ID ถูก

  • Player ที่ต้องเห็น Entity อยู่ Bucket เดียวกัน

จากนั้นใช้:

GetEntityRoutingBucket(entity)

ตรวจผลจริง.

FiveM Routing Bucket Vehicle ไม่ตาม Player

Routing Bucket ไม่ได้หมายความว่า Entity ทุกตัวที่ Player เคยใช้จะถูกย้ายตาม Player อัตโนมัติ

ถ้า Gameplay ต้องการรถคันหนึ่งติดตาม Player เข้า Instance ต้องกำหนด Bucket ของรถให้ตรงด้วย

SetPlayerRoutingBucket(
    source,
    bucket
)

SetEntityRoutingBucket(
    vehicle,
    bucket
)

FiveM Routing Bucket Voice Chat แยกอัตโนมัติไหม

อย่าคิดว่า Routing Bucket ควรเป็นตัวจัด Voice Routing ของ Resource ทุกระบบโดยอัตโนมัติ

Voice Resource อาจมี Channel, Proximity หรือ Routing Logic ของตัวเอง

ดังนั้นหาก Player คนละ Bucket ยังได้ยินกัน ให้ตรวจ Voice Resource Configuration เพิ่ม ไม่ควรแก้ Entity Bucket แบบสุ่ม

FiveM Routing Bucket กับ State Bags ใช้ร่วมกันได้ไหม

ได้

Cfx.re แนะนำ State Bags สำหรับแนบ Attributes ให้ Entities ซึ่ง Clients ที่เกี่ยวข้องสามารถอ่านได้ตาม State Awareness/Scope.

ตัวอย่าง:

Bucket 500
↓
Vehicle
↓
State Bag
session:id = 123
vehicle:locked = true

ช่วยให้ Resource รู้ทั้ง Instance และ Runtime State ของ Entity

FiveM Routing Bucket กับ Network ID ต่างกันอย่างไร

Routing Bucket บอกว่า:

Entity อยู่ Game State ไหน

Network ID บอกว่า:

Entity ตัวไหนใน Network

ดังนั้น:

Entity
├── NetID = 145
└── Bucket = 500

เป็นข้อมูลคนละหน้าที่

FiveM Routing Bucket กับ Entity Ownership ต่างกันอย่างไร

Routing Bucket กำหนด Visibility/Game State

Entity Ownership กำหนดว่า Client ใดกำลังควบคุม Networked Entity

Player อาจอยู่ Bucket เดียวกับ Vehicleและเห็นรถ แต่ไม่ได้หมายความว่า Player นั้นเป็น Current Network Owner เสมอไป

FiveM Routing Bucket ใช้จำนวนมากได้ไหม

ใช้ได้ตาม Architecture แต่ Cfx.re ระบุว่า แต่ละ Routing Bucket มี Memory Cost จึงไม่ควรสร้าง Bucket จำนวนมหาศาลโดยไม่จำเป็นหรือไม่ Cleanup.

ออกแบบ Bucket Allocation ให้เหมาะกับจำนวน Concurrent Sessions จริง

FiveM Routing Bucket ควรใช้กับ Interior ไหม

Cfx.re ระบุว่าไม่ควรใช้ Routing Bucket เป็น Use Case หลักสำหรับ Interiors.

Routing Bucket เหมาะกับ:

Character Selection
Party
Session
Multi-mode
Private Instance

มากกว่า

Checklist FiveM Routing Bucket สำหรับ Production

ตรวจว่า:

  1. OneSync ทำงาน

  2. Bucket IDs มี Convention

  3. Server เป็นผู้ Assign Bucket

  4. ไม่เชื่อ Bucket ID จาก Client

  5. Player Bucket ถูก

  6. Entity Bucket ถูก

  7. Player และ Entity อยู่ Bucket เดียวกันเมื่อควรเห็นกัน

  8. Character Instance ถูก Cleanup

  9. Party Instance ถูก Cleanup

  10. Player Disconnect ถูกลบจาก Session

  11. Resource Restart มี Recovery

  12. Entity Lockdown ถูก Mode

  13. Population ถูกเปิด/ปิดตาม Design

  14. ไม่ใช้ Interior เป็น Bucket แบบสุ่ม

  15. Event ตรวจ Session/Bucket ฝั่ง Server

  16. NetID ไม่ถูกใช้แทน Bucket

  17. Entity Ownership ไม่ถูกสับสนกับ Bucket

  18. ไม่สร้าง Buckets จำนวนมากโดยไม่มี Cleanup

  19. ทดสอบ Player หลายคน

  20. ทดสอบผู้เล่นออก Instance

  21. ทดสอบ Disconnect ใน Instance

  22. ทดสอบ Resource Restart

  23. ทดสอบ Vehicle/Ped/Object ใน Instance

  24. ตรวจ Server Console

  25. ตรวจ Performance เมื่อมี Concurrent Instances จำนวนมาก

FAQ FiveM Routing Bucket

FiveM Routing Bucket คืออะไร

เป็นระบบ Instance/Dimension ของ FiveM ที่สามารถ Assign Players และ Entities ไปยัง Game State แยกกัน โดยผู้ที่อยู่ Bucket เดียวกันจะเห็น Players/Entities ภายใน Bucket เดียวกัน.

Routing Bucket ใช้ทำ Character Selection ได้ไหม

ได้ Cfx.re ระบุ Character Screen แบบ Instanced เป็น Use Case โดยตรง.

Routing Bucket ใช้ทำ Party ได้ไหม

ได้ Session/Party System เป็นหนึ่งใน Use Cases ที่ Cfx.re แนะนำ.

ย้าย Player เข้า Bucket ใช้คำสั่งอะไร

ใช้:

SetPlayerRoutingBucket(
    source,
    bucketId
)

ดูว่า Player อยู่ Bucket ไหนอย่างไร

ใช้:

GetPlayerRoutingBucket(source)

ย้าย Entity เข้า Bucket อย่างไร

ใช้:

SetEntityRoutingBucket(
    entity,
    bucketId
)

Cfx.re รวม Native นี้ไว้ใน Routing Bucket API ของ OneSync.

Player เข้า Bucket แล้วรถหายเพราะอะไร

สาเหตุหนึ่งที่พบบ่อยคือ Player และ Vehicle อยู่คนละ Routing Bucket ให้ตรวจ GetPlayerRoutingBucket() กับ GetEntityRoutingBucket() ก่อน.

Routing Bucket ใช้ทำ Interior ได้ไหม

Cfx.re ระบุชัดว่า Interiors ไม่ใช่ Use Case ที่แนะนำสำหรับ Routing Buckets.

Routing Bucket มีผลต่อ Memory ไหม

มี Cfx.re ระบุว่าแต่ละ Routing Bucket มี Memory Cost ดังนั้นควรสร้างและจัด Lifecycle อย่างเป็นระบบ.

strict Entity Lockdown คืออะไร

เป็น Mode ที่ไม่อนุญาตให้ Clients สร้าง Entities ภายใน Bucket นั้น.

ประเด็นสำคัญ

FiveM Routing Bucket เป็นระบบ Instance ของ OneSync ที่ใช้แยก Players และ Entities เป็น Game State คนละชุด โดย Cfx.re ระบุ Use Cases หลักอย่าง Multi-mode Server, Party/Session และ Character Selection พร้อมทั้งระบุว่า Interior ไม่ใช่ Use Case ที่ควรใช้ Routing Bucket เป็นวิธีหลัก.

สิ่งที่ต้องจำให้แม่นคือ:

SetPlayerRoutingBucket
= ย้าย Player

SetEntityRoutingBucket
= ย้าย Entity

GetPlayerRoutingBucket
= ดู Player Bucket

GetEntityRoutingBucket
= ดู Entity Bucket

หาก Player เข้า Instance แล้วรถหรือ Entity หาย ให้ตรวจ Player Bucket เทียบกับ Entity Bucket ก่อน เพราะ Entity จะต้องถูก Route ไปยัง Game State ที่เหมาะสมเช่นเดียวกับ Player.

แต่ละ Bucket ยังสามารถกำหนด Population และ Entity Lockdown ของตัวเอง โดยปัจจุบันมี strict, relaxed, inactive และสำหรับ GTAV Enhanced มี full เพิ่มเข้ามา.

Server ที่ใช้ Instances จำนวนมากควรมี Bucket Allocator + Session Manager + Cleanup เนื่องจาก Cfx.re ระบุว่า Routing Buckets มี Memory Cost และไม่ควรสร้าง Bucket จำนวนมากโดยไม่มี Lifecycle Management.

สำหรับผู้อ่าน comsiam ให้จำสูตร “Player Bucket + Entity Bucket = Instance ที่มองเห็น” และ comsiam แนะนำให้ Server เป็นผู้เลือก Bucket ID ตรวจ Bucket ทุกครั้งก่อนทำ Session Action และ Cleanup Player/Entity เมื่อ Instance จบ เพื่อป้องกันปัญหาผู้เล่นหาย รถหาย หรือค้างอยู่คนละโลกหลัง Resource Restart

Comments

Popular posts from this blog

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

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

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