FiveM Routing Bucket คืออะไร
FiveM Routing Bucket คือระบบสำหรับแยก Player และ Entity ออกเป็นโลกหรือ Instance คนละชุดภายใน Server เดียวกัน แนวคิดคล้าย Dimension, Virtual World หรือ Instance ที่พบใน Multiplayer Server รูปแบบอื่น
ตัวอย่าง Server มีผู้เล่น 100 คน
ปกติทุกคนอยู่
Bucket 0
แต่เราสามารถย้าย Player กลุ่มหนึ่งไป
Bucket 10
และอีกกลุ่มไป
Bucket 20
ผลคือ
Bucket 0
→ Main World
Bucket 10
→ Mission A
Bucket 20
→ Mission B
Player และ Entity ที่อยู่คนละ Routing Bucket จะถูกแยกออกจากกันตามระบบ Routing ของ OneSync
ตัวอย่างย้าย Player ไป Bucket 10
SetPlayerRoutingBucket(
source,
10
)
และถ้ามี Vehicle ของ Mission ก็ควรย้าย Vehicle ไป Bucket เดียวกัน
SetEntityRoutingBucket(
vehicle,
10
)
Routing Bucket จึงเหมาะมากกับระบบอย่าง
Character Selection
Mission Instance
Party
Lobby
Multi-mode Server
Private Session
Match
Dungeon/Scenario
แต่มีข้อสำคัญคือ Cfx.re ระบุชัดว่า Routing Bucket ไม่ใช่เครื่องมือที่แนะนำสำหรับการทำ Interior Instance ทั่วไป ซึ่งจะอธิบายเพิ่มเติมด้านล่าง
① Routing Bucket คืออะไร
Routing Bucket คือการแบ่ง Game State ออกเป็นกลุ่ม
สมมติ
Player A
Bucket 1
Player B
Bucket 1
Player C
Bucket 2
Player A กับ B อยู่ Bucket เดียวกัน
จึงสามารถอยู่ใน Routing Context เดียวกัน
แต่ Player C อยู่ Bucket 2
จึงถูกแยกออก
Concept คือ
Server เดียว
↓
หลาย Routing Buckets
↓
หลาย Instance
ไม่ต้องเปิด FiveM Server แยกกัน
② Routing Bucket เหมือน Dimension ไหม
ใกล้เคียงมาก
Cfx.re เองอธิบายว่า Routing Bucket มี Concept คล้าย
Dimension
Virtual World
Instance
จาก Multiplayer Platform อื่น
ดังนั้นหากเคยเขียนระบบ
Dimension 0
Dimension 1
Dimension 2
สามารถมอง FiveM Routing Bucket เป็น Concept ใกล้เคียงกันได้
แต่ Implementation และ Networking Behavior ของ FiveM มีรายละเอียดเฉพาะของตัวเอง
③ Routing Bucket ต้องใช้ OneSync ไหม
ใช่
Routing Bucket เป็นส่วนหนึ่งของ OneSync/State Awareness Architecture
Resource ที่พึ่งระบบนี้จึงควรออกแบบให้ทำงานใน Environment ที่เปิด OneSync ตาม Requirement
ใน fxmanifest.lua ยังสามารถระบุ Constraint เช่น
dependencies {
'/onesync'
}
เพื่อบอกว่า Resource ต้องการ State Awareness
④ Bucket 0 คืออะไร
โดยทั่วไป
Bucket 0
คือ Main Routing Bucket
Player ที่ไม่ได้ถูกย้ายไป Instance อื่นมักอยู่ Bucket 0
ตัวอย่างเมื่อ Player จบ Mission
SetPlayerRoutingBucket(
source,
0
)
คือย้ายกลับ Main World
ดังนั้นระบบ Instance จำนวนมากใช้ Pattern
เข้า Mission
→ Bucket X
ออก Mission
→ Bucket 0
⑤ SetPlayerRoutingBucket คืออะไร
ใช้เปลี่ยน Routing Bucket ของ Player
ตัวอย่าง
SetPlayerRoutingBucket(
source,
15
)
ตอนนี้ Player จะอยู่ Bucket 15
ในระบบ Mission อาจใช้
local bucket =
1000 + source
SetPlayerRoutingBucket(
source,
bucket
)
เพื่อสร้าง Private Instance ของ Player
แต่การ Generate Bucket ID ต้องออกแบบไม่ให้ชนกัน
⑥ GetPlayerRoutingBucket คืออะไร
ใช้ตรวจว่า Player อยู่ Bucket ไหน
ตัวอย่าง
local bucket =
GetPlayerRoutingBucket(
source
)
print(
'Player bucket:',
bucket
)
มีประโยชน์สำหรับ
Validation
Debug
Party System
Mission
Instance Cleanup
Server สามารถตรวจ Player Bucket ก่อนทำ Action สำคัญได้
⑦ SetEntityRoutingBucket คืออะไร
ใช้กำหนด Routing Bucket ของ Entity
ตัวอย่าง Vehicle
SetEntityRoutingBucket(
vehicle,
15
)
หาก Player อยู่ Bucket 15 และ Vehicle ก็อยู่ Bucket 15 ทั้งคู่จะอยู่ Routing Context เดียวกัน
Entity สามารถเป็น
Vehicle
Ped
Object
ตามระบบที่รองรับ
⑧ GetEntityRoutingBucket คืออะไร
ใช้ตรวจว่า Entity อยู่ Bucket ไหน
local bucket =
GetEntityRoutingBucket(
vehicle
)
print(bucket)
ช่วย Debug ปัญหาเช่น
Player เห็นรถไม่ได้
แล้วพบว่า
Player Bucket = 10
Vehicle Bucket = 0
ทั้งสองอยู่คนละ Bucket
⑨ Player กับ Vehicle ต้องอยู่ Bucket เดียวกันไหม
ถ้าต้องการให้ Vehicle เป็นส่วนหนึ่งของ Instance เดียวกับ Player โดยทั่วไปควรจัดให้อยู่ Bucket เดียวกัน
เช่น
Player
Bucket 50
Mission Vehicle
Bucket 50
Mission Ped
Bucket 50
Mission Props
Bucket 50
ไม่ควรย้ายเฉพาะ Player แล้วปล่อย Mission Entities อยู่ Bucket 0 โดยไม่คิดถึง Routing
⑩ ตัวอย่างสร้าง Mission Instance
Server
local bucket = 100
SetPlayerRoutingBucket(
source,
bucket
)
local ped =
GetPlayerPed(source)
local coords =
GetEntityCoords(ped)
local vehicle =
CreateVehicleServerSetter(
joaat('sultan'),
'automobile',
coords.x + 5.0,
coords.y,
coords.z,
0.0
)
SetEntityRoutingBucket(
vehicle,
bucket
)
ตอนนี้ Player กับ Mission Vehicle อยู่ Instance เดียวกัน
⑪ Routing Bucket แยก Player อย่างไร
สมมติ Player สองคนยืน Coordinates เดียวกัน
Player A
x=100 y=200 z=30
Bucket 10
Player B
x=100 y=200 z=30
Bucket 20
แม้ Coordinates เหมือนกัน
แต่ Routing Context ต่างกัน
จึงไม่ควรมองว่าอยู่ในโลก Multiplayer เดียวกันในลักษณะปกติ
นี่ทำให้สามารถใช้พื้นที่เดียวกันสำหรับ Mission หลาย Instance ได้
⑫ Mission หลายทีมใช้พื้นที่เดียวกันได้ไหม
ได้ และเป็น Use Case ที่ดีมาก
สมมติ Mission Warehouse อยู่ Coordinates เดียว
Party A
Bucket 101
Party B
Bucket 102
Party C
Bucket 103
ทุก Party สามารถใช้พื้นที่เดียวกันในคนละ Instance โดยไม่ต้องสร้าง Map Copy หลายแห่ง
⑬ Party System ใช้ Routing Bucket อย่างไร
เมื่อ Party เริ่ม Mission
Server Generate Bucket
local bucket =
CreatePartyBucket()
แล้ว Player ทุกคนใน Party ถูกย้ายไป Bucket เดียวกัน
for _, playerId in ipairs(
partyPlayers
) do
SetPlayerRoutingBucket(
playerId,
bucket
)
end
จากนั้น Spawn Mission Entities ใน Bucket เดียวกัน
⑭ Private Instance สำหรับ Player คนเดียว
Character Selection เป็นตัวอย่างที่ Cfx.re ระบุว่าเหมาะกับ Routing Bucket
Flow เช่น
Player Connect
↓
Bucket ส่วนตัว
↓
Character Selection
↓
เลือก Character
↓
โหลดข้อมูล
↓
Bucket 0
↓
Main World
ช่วยไม่ให้ Player ที่ยังเลือก Character ไปปรากฏในโลกหลัก
⑮ Character Selection ใช้ Bucket แบบไหนดี
สามารถ Generate Unique Bucket จาก Server State
ตัวอย่าง Concept
local bucket =
10000 + source
จากนั้น
SetPlayerRoutingBucket(
source,
bucket
)
หลัง Character พร้อมแล้ว
SetPlayerRoutingBucket(
source,
0
)
แต่ Production System ควรมี Bucket Allocator ที่ควบคุม Collision และ Reuse อย่างชัดเจน
⑯ Lobby ใช้ Routing Bucket ได้ไหม
ได้
ตัวอย่าง
Lobby A
Bucket 200
Lobby B
Bucket 201
Lobby C
Bucket 202
Player ใน Lobby เดียวกันสามารถถูกจัดอยู่ใน Bucket เดียวกัน
จากนั้นเมื่อ Match เริ่มอาจใช้ Bucket เดิมหรือย้ายไป Match Bucket ตาม Architecture
⑰ Multi-mode Server ใช้ได้ไหม
ได้ และเป็นหนึ่งใน Use Case ที่ Cfx.re ระบุโดยตรง
Server หนึ่งอาจมี
Roleplay
Deathmatch
Racing
Training
แยกกัน
แต่ต้องออกแบบระบบอื่นร่วมด้วย เช่น
Player Data
Commands
Voice
UI
Economy
Events
Routing Bucket แยก Networking Context แต่ไม่ได้แยกทุกระบบใน Resource ให้อัตโนมัติ
⑱ Routing Bucket แยก Database ไหม
ไม่
Player อยู่คนละ Bucket แต่ Server Resource และ Database ยังคงเป็นระบบ Server เดียวกัน
สมมติ
Player A
Bucket 10
Player B
Bucket 20
ทั้งคู่ยังสามารถ Query
players
vehicles
inventory
ใน Database เดียวกันได้ถ้า Script ออกแบบแบบนั้น
Routing Bucket ไม่ใช่ Database Isolation
⑲ Routing Bucket แยก Lua Variable ไหม
ไม่
ตัวอย่าง Server
local players = {}
Table นี้ไม่ได้ถูกสร้างแยกต่อ Bucket อัตโนมัติ
ถ้าต้องการ State แยก Instance ต้องเขียนเอง เช่น
local instances = {}
instances[bucket] = {
players = {},
vehicles = {},
missionState = {}
}
Routing Bucket จัด Network Routing ไม่ได้สร้าง Application State Architecture ให้ทั้งหมด
⑳ Routing Bucket แยก Events อัตโนมัติไหม
อย่าคิดว่า Event ทุกตัวจะถูก Filter ด้วย Bucket ให้อัตโนมัติใน Business Logic ของคุณ
ถ้า Serverทำ
TriggerClientEvent(
'mission:update',
-1,
data
)
-1 ยังหมายถึง Broadcast ไป Clients ตาม Event Semantics
ดังนั้นระบบ Instance ควร Target เฉพาะ Players ที่เกี่ยวข้อง
เช่น
for _, playerId in ipairs(
instance.players
) do
TriggerClientEvent(
'mission:update',
playerId,
data
)
end
㉑ อย่า Broadcast Event ทุกคนแล้วหวัง Bucket Filter
Architecture ที่ดีควรรู้ว่า
Bucket 150
มี Player ใครบ้าง
แล้วส่ง Event เฉพาะกลุ่ม
ช่วยลด
Network Traffic
Client Processing
Data Exposure
โดยเฉพาะ Server ขนาดใหญ่
㉒ Routing Bucket กับ State Bag
สามารถใช้ร่วมกันได้ดี
ตัวอย่าง Mission Entity
Vehicle
Bucket = 50
พร้อม State
mission:id = 125
mission:team = 2
ผ่าน State Bag
Routing Bucket บอกว่า Entity อยู่ Instance ไหน
State Bag บอก Custom State ของ Entity
สองระบบทำหน้าที่ต่างกัน
㉓ Routing Bucket กับ Entity Ownership
Entity ใน Routing Bucket ยังมี Network Ownership ตาม OneSync
Bucket ไม่ได้ทำให้ Server กลายเป็น Network Owner ของ Entity ทั้งหมด
เช่น
Vehicle
Bucket 50
↓
Network Owner
Client A
Ownership ยังสามารถ Migration ได้ตามระบบ
㉔ Routing Bucket กับ Network ID
Entity ที่เป็น Networked Entity ยังมี Network ID
ตัวอย่าง
Vehicle
Net ID = 84
Bucket = 50
Network ID บอกว่าเป็น Entity ตัวไหน
Routing Bucket บอกว่า Entity อยู่ Routing Context ไหน
อย่าใช้ข้อมูลสองอย่างนี้แทนกัน
㉕ Routing Bucket กับ Scope
Bucket เป็น Boundary สำคัญของ Routing
Entity และ Player ต้องอยู่ใน Routing Context ที่เกี่ยวข้องก่อนจึงจะเกิด Scope/Visibility ตาม OneSync
ดังนั้นเมื่อ Debug Entity หาไม่เจอ ต้องตรวจทั้ง
Network ID
Scope
Routing Bucket
ไม่ใช่ดูแค่ Coordinates
㉖ Player อยู่ใกล้กันแต่ไม่เห็นกัน เพราะอะไร
หนึ่งในสาเหตุสำคัญคือ Routing Bucket ต่างกัน
ตรวจ Server
local bucket =
GetPlayerRoutingBucket(
source
)
print(bucket)
ถ้าสอง Player อยู่
Player A = 0
Player B = 50
แม้ Coordinates เหมือนกันก็สามารถถูกแยกด้วย Routing Bucket ได้
㉗ รถหายหลังย้าย Player เข้า Bucket เพราะอะไร
สาเหตุที่พบบ่อยคือย้ายเฉพาะ Player
SetPlayerRoutingBucket(
source,
50
)
แต่รถยังอยู่
Bucket 0
จึงถูกแยกออกจาก Player
ถ้ารถต้องตามเข้า Mission ต้อง Set Entity Bucket ด้วย
SetEntityRoutingBucket(
vehicle,
50
)
㉘ ย้าย Player พร้อมรถทำอย่างไร
ต้อง Resolve Vehicle ฝั่ง Server และตรวจ Ownership/Entity ก่อน
Concept:
Player
↓
Vehicle
↓
Validate
↓
SetEntityRoutingBucket(vehicle, bucket)
↓
SetPlayerRoutingBucket(player, bucket)
Order และ State Handling ควรออกแบบตามระบบจริง
โดยเฉพาะรถที่มีผู้โดยสารหลายคน
㉙ Vehicle มีผู้เล่นหลายคนต้องทำอย่างไร
ถ้ารถมี Driver และ Passengers
ไม่ควรย้าย Driver คนเดียวไป Bucket ใหม่แล้วปล่อย Passenger อยู่ Bucket เดิม
ระบบควร
ตรวจ occupants
↓
กำหนด Party/Session
↓
ย้าย Players ที่เกี่ยวข้อง
↓
ย้าย Vehicle
ตาม Gameplay Requirement
ไม่เช่นนั้นอาจเกิด State แปลก ๆ
㉚ Routing Bucket กับ Ped และ Object
ไม่ใช่แค่ Vehicle
Mission อาจมี
NPC
Enemies
Props
Doors
Mission Objects
Entities เหล่านี้ควรถูกกำหนด Bucket เดียวกับ Mission ตาม Architecture
ตัวอย่าง
SetEntityRoutingBucket(
missionPed,
bucket
)
SetEntityRoutingBucket(
missionObject,
bucket
)
㉛ Population ใน Routing Bucket คืออะไร
แต่ละ Routing Bucket มี World Grid ของตัวเองสำหรับ Population Ownership
FiveM ยังมี API
SetRoutingBucketPopulationEnabled(
bucket,
enabled
)
สำหรับเปิดหรือปิด Population ใน Bucket
เช่น Private Character Screen อาจไม่ต้องการ Ambient NPC/Traffic
㉜ วิธีปิด Population ใน Bucket
ตัวอย่าง
SetRoutingBucketPopulationEnabled(
100,
false
)
ตอนนี้ Bucket 100 ถูกกำหนดไม่ให้ Population ทำงานตาม Policy นั้น
เหมาะกับ
Character Screen
Controlled Mission
Private Scene
Lobby
ที่ไม่ต้องการ Random NPC/Traffic เข้ามารบกวน
㉝ ควรปิด Population ทุก Bucket ไหม
ไม่
ขึ้นกับ Gameplay
Racing Instance อาจต้องการ Traffic หรือไม่ต้องการก็ได้
Mission Open World อาจต้องการ Population
Character Screen ส่วนใหญ่ไม่ต้องการ
ดังนั้นกำหนดตาม Requirement
Controlled Instance
→ อาจปิด
Open-world Instance
→ อาจเปิด
㉞ Entity Lockdown Mode ต่อ Bucket คืออะไร
Routing Bucket สามารถตั้ง Entity Lockdown Mode ได้
เช่น
SetRoutingBucketEntityLockdownMode(
bucket,
'strict'
)
ใช้กำหนดว่าฝั่ง Client สามารถสร้าง Entity ใน Bucket นั้นได้มากแค่ไหน
นี่เป็น Feature สำคัญสำหรับ Server Security
㉟ Lockdown Mode มีอะไรบ้าง
เอกสาร OneSync ปัจจุบันระบุ Mode หลัก เช่น
strict
relaxed
inactive
และสำหรับ FiveM GTAV Enhanced มี full เพิ่มในเอกสารปัจจุบัน
ความหมายโดยย่อคือ
strict
→ Client สร้าง Entity ไม่ได้
relaxed
→ จำกัด Script-owned Client Entities
inactive
→ Client สร้าง Entity ได้ตามปกติ
ส่วน full มีข้อกำหนดเฉพาะ GTAV Enhanced
㊱ strict เหมาะกับอะไร
เหมาะกับ Instance ที่ต้องการ
Server-authoritative Entity Creation
เช่น Mission
Client
↓
ขอ Spawn Vehicle
↓
Server Validate
↓
Server Create Vehicle
↓
Set Entity Bucket
แทนปล่อย Client สร้าง Entity ได้ตามใจ
㊲ ตัวอย่าง Bucket แบบ strict
local bucket = 100
SetRoutingBucketEntityLockdownMode(
bucket,
'strict'
)
SetRoutingBucketPopulationEnabled(
bucket,
false
)
SetPlayerRoutingBucket(
source,
bucket
)
ตอนนี้ Bucket ถูกควบคุมเข้มขึ้น
Mission Entities ควรถูกสร้างจาก Server ตาม Architecture
㊳ relaxed ต่างจาก strict อย่างไร
relaxed จำกัดเฉพาะ Client-created Entities บางประเภทตาม Script Ownership Rule
ส่วน
strict
เข้มกว่า โดยไม่ให้ Client สร้าง Entity ใน Bucket นั้น
ถ้า Server Resource เก่าพึ่ง Client Spawn Vehicle/Ped/Object มาก การเปิด strict อาจทำให้ Resource ทำงานไม่ได้
ต้อง Audit ก่อนใช้
㊴ inactive คืออะไร
inactive หมายถึงไม่มี Entity Lockdown ในลักษณะที่ Mode อื่นกำหนด
Client สามารถสร้าง Entity ตามระบบปกติ
เหมาะกับ Bucket ที่ต้อง Compatibility สูง แต่ Security ของ Client-created Entity ต้องจัดการด้วยวิธีอื่น
㊵ Routing Bucket เป็น Security Boundary 100% ไหม
ไม่ควรมองแบบนั้น
มันช่วยแยก Routing Context แต่ Application Security ยังต้องมี
Server Validation
Permission
Event Security
Database Validation
State Validation
ตัวอย่าง Player อยู่ Bucket 50 ไม่ได้หมายความว่า Server Event จาก Player ควรเชื่อถือทันที
㊶ ตรวจ Bucket ใน Server Event ได้ไหม
ได้ และมีประโยชน์มาก
สมมติ Mission Complete ต้องเกิดเฉพาะ Bucket ของ Mission
local playerBucket =
GetPlayerRoutingBucket(
src
)
if playerBucket ~=
mission.bucket then
return
end
ช่วยเพิ่ม Server-side State Validation
㊷ Bucket ID จาก Client เชื่อได้ไหม
ไม่ควร
อย่าให้ Clientส่ง
myBucket = 50
แล้ว Serverเชื่อว่าผู้เล่นอยู่ Bucket 50
Serverสามารถหาเองด้วย
GetPlayerRoutingBucket(
source
)
จึงไม่มีเหตุผลให้ Clientเป็น Authority ของข้อมูลนี้
㊸ Client ขอเลือก Bucket เองได้ไหม
Client สามารถส่ง Request เช่น
ฉันต้องการเข้า Party 15
แต่ Server ควรเป็นคนตัดสิน
Party มีจริงไหม?
Player เป็นสมาชิกไหม?
Mission เริ่มหรือยัง?
Bucket ของ Party คืออะไร?
แล้ว Server จึง
SetPlayerRoutingBucket(
source,
party.bucket
)
ไม่ควรเปิด Event แบบ
setMyBucket(anyNumber)
โดยไม่มี Validation
㊹ Event setBucket แบบ Generic อันตรายอย่างไร
ตัวอย่างไม่ดี
RegisterNetEvent(
'instance:setBucket',
function(bucket)
SetPlayerRoutingBucket(
source,
bucket
)
end
)
Clientสามารถพยายามเลือก Bucket ใดก็ได้
อาจเข้า
Private Mission
Character Instance
Admin Instance
Party อื่น
ถ้าระบบพึ่ง Bucket Isolation
นี่เป็นช่องโหว่เชิง Logic
㊺ วิธีที่ดีกว่าสำหรับ Mission
Client
TriggerServerEvent(
'mission:join',
missionId
)
Server
Validate missionId
↓
Validate membership
↓
หา mission.bucket จาก Server
↓
SetPlayerRoutingBucket
Client ไม่จำเป็นต้องรู้หรือควบคุม Bucket ID โดยตรง
㊻ Bucket Allocator คืออะไร
Server ขนาดใหญ่ควรมีระบบแจก Bucket IDs
เช่น
local nextBucket = 1000
เมื่อสร้าง Instance
nextBucket =
nextBucket + 1
local bucket =
nextBucket
แต่ระบบจริงต้องคิดถึง
Reuse
Cleanup
Collision
Restart
Maximum Active Instances
ไม่ควรสุ่ม Bucket ID แบบไม่มีการจัดการ
㊼ Bucket ID ต้อง Unique ตลอดไปไหม
ไม่จำเป็นต้อง Unique ข้ามเวลา ถ้า Instance เก่าถูก Cleanup สมบูรณ์แล้วสามารถ Reuse Bucket ID ได้ตามระบบของคุณ
ตัวอย่าง
Bucket 100
→ Mission A
→ Mission จบ
→ Cleanup
→ ไม่มี Player/Entity
ภายหลัง
Bucket 100
→ Mission B
ได้ถ้า State เก่าถูกล้างหมด
㊽ Cleanup Routing Bucket สำคัญไหม
สำคัญมาก
เมื่อ Mission จบควร
Players
→ Bucket 0
Mission Entities
→ Delete หรือ Move ตาม Requirement
Instance State
→ Clear
Bucket Registry
→ Release
ไม่เช่นนั้นอาจเกิด
Player ติด Instance
Entity ค้าง
State Leak
Bucket ID ไม่ถูก Reuse
Memory/Resource Usage เพิ่ม
㊾ Player Disconnect ขณะอยู่ Instance ทำอย่างไร
Server ควร Handle
AddEventHandler(
'playerDropped',
function()
local src =
source
-- remove from instance
-- cleanup instance if empty
end
)
ถ้า Player คนสุดท้ายออก
Instance อาจถูก Destroy และ Mission Entities Cleanup
ตาม Architecture
㊿ Player Resource Restart แล้ว Bucket หายไหม
Routing Bucket State อยู่ระดับ Server Networking ไม่ใช่ Lua Variable ธรรมดาของ Resource เพียงอย่างเดียว
ถ้า Resource Restart แต่ไม่ได้ Reset Players อาจเกิด State ที่ Resource Registry กับ Actual Bucket ไม่ตรงกัน
Resource ที่ดูแล Instance ควรมี Recovery/Initialization Strategy ตามความสำคัญของระบบ
51 onPlayerBucketChange คืออะไร
FiveM มี Server Event
onPlayerBucketChange
ซึ่งถูกเรียกเมื่อ Player เปลี่ยน Routing Bucket
Parameters คือ
player
bucket
oldBucket
ตัวอย่าง
AddEventHandler(
'onPlayerBucketChange',
function(
player,
bucket,
oldBucket
)
print(
player,
oldBucket,
bucket
)
end
)
เหมาะกับ Debug, Audit หรือ Instance Tracking
52 onEntityBucketChange คืออะไร
มี Event
onEntityBucketChange
เมื่อ Entity เปลี่ยน Routing Bucket
ได้รับ
entity
bucket
oldBucket
ตัวอย่าง
AddEventHandler(
'onEntityBucketChange',
function(
entity,
bucket,
oldBucket
)
print(
entity,
oldBucket,
bucket
)
end
)
ช่วย Debug Vehicle/Ped/Object ที่ถูกย้ายผิด Bucket
53 Routing Bucket ใช้ทำ Interior ได้ไหม
Cfx.re ระบุอย่างชัดเจนว่า Interior ไม่ใช่ Use Case ที่แนะนำสำหรับ Routing Buckets
เหตุผลคือ GTA V มี Interior ที่สามารถมองออกไปเห็น Outside World ได้ และ Routing Bucket ตัด Routing Context ในลักษณะที่ไม่เหมาะกับ Use Case เหล่านี้
เอกสารแนะนำ Traditional Conceal Natives หรือแนวทาง Routing แบบ 3D-scoped ที่มีการกล่าวถึงสำหรับอนาคตแทน
ดังนั้นอย่าใช้
Interior ทุกห้อง
=
Bucket ใหม่
โดยอัตโนมัติ
54 แล้ว MLO ควรใช้ Routing Bucket ไหม
ไม่ควรตอบว่า MLO ทุกตัวต้องใช้ Bucket
ถ้าเป็น Interior ปกติที่ Player ควรยังอยู่ใน Shared World Cfx.re ไม่แนะนำ Routing Bucket เป็น Default Solution
Routing Bucket เหมาะกับ
Session / Instance
มากกว่า
แค่เดินเข้าตึกหนึ่งหลัง
ต้องดู Gameplay Requirement จริง
55 Character Selection เหมาะกว่าทำ Interior
ใช่ เพราะ Character Selection คือ Instance แยกชัดเจน
Player ยังไม่ควรอยู่ร่วมกับ Main Gameplay
จึงสามารถ
Connect
↓
Private Bucket
↓
Select Character
↓
Load Character
↓
Bucket 0
นี่เป็นหนึ่งใน Use Cases ที่ Cfx.re ยกตัวอย่างโดยตรง
56 Routing Bucket มี Cost ไหม
มี
เอกสาร Cfx.re ปัจจุบันระบุว่าทุก Routing Bucket มี Memory Cost
ดังนั้นไม่ควรสร้าง Bucket จำนวนมหาศาลโดยไม่มี Lifecycle
ระบบควร
Create เมื่อจำเป็น
Reuse เมื่อเหมาะสม
Cleanup หลังใช้
ไม่สร้าง Instance ถาวรโดยไม่จำเป็น
โดยเฉพาะ Server ขนาดใหญ่
57 Bucket ต่อ Player ตลอดเวลา ดีไหม
ขึ้นกับระบบ
Character Selection ชั่วคราวใช้ Private Bucket ต่อ Playerได้
แต่ถ้า Server มีผู้เล่นจำนวนมากและสร้าง Bucket ถาวรให้ Player ทุกคนโดยไม่จำเป็น ต้องคำนึงถึง Memory Cost และ Complexity
อย่าใช้ Bucket เพียงเพราะทำได้
ใช้เมื่อมี Requirement ด้าน Isolation จริง
58 Routing Bucket Debug อย่างไร
สร้าง Command ฝั่ง Server เช่น
RegisterCommand(
'mybucket',
function(source)
if source == 0 then
return
end
local bucket =
GetPlayerRoutingBucket(
source
)
print(
('Player %s bucket %s')
:format(
source,
bucket
)
)
end,
false
)
สำหรับ Entity สามารถตรวจ
local bucket =
GetEntityRoutingBucket(
entity
)
และใช้ onPlayerBucketChange / onEntityBucketChange ช่วย Log การเปลี่ยนแปลง
59 Checklist ก่อนใช้ FiveM Routing Bucket
ตรวจอย่างน้อย
① ต้องการ Instance จริงหรือไม่?
② OneSync พร้อมหรือไม่?
③ Bucket 0 ใช้เป็น Main World หรือไม่?
④ Bucket ID มาจาก Server หรือยัง?
⑤ มี Bucket Allocator หรือไม่?
⑥ Players ใน Party ถูกย้ายครบไหม?
⑦ Vehicles ถูกย้าย Bucket หรือยัง?
⑧ Mission Peds ถูกย้ายหรือยัง?
⑨ Mission Objects ถูกย้ายหรือยัง?
⑩ Population ควรเปิดหรือปิด?
⑪ Entity Lockdown Mode ควรเป็นอะไร?
⑫ Event ถูกส่งเฉพาะ Instance Players หรือไม่?
⑬ Server Event ตรวจ Player Bucket หรือไม่?
⑭ Client สามารถเลือก Bucket เองได้หรือไม่?
⑮ Instance State ถูกเก็บ Server-side หรือไม่?
⑯ Player Disconnect ถูก Cleanup หรือไม่?
⑰ Instance ว่างแล้วถูก Destroy หรือไม่?
⑱ Entities ถูก Cleanup หรือไม่?
⑲ Bucket ID ถูก Release หรือไม่?
⑳ กำลังใช้ Bucket กับ Interior ที่ไม่เหมาะหรือไม่?
㉑ จำนวน Buckets มากเกินจำเป็นหรือไม่?
㉒ Resource Restart Recovery ถูกคิดไว้หรือไม่?
⑥⓪ ตัวอย่าง Routing Bucket สำหรับ Mission แบบสมบูรณ์
server.lua
local instances = {}
local nextBucket = 1000
local function createInstance(
owner
)
nextBucket =
nextBucket + 1
local bucket =
nextBucket
instances[bucket] = {
owner = owner,
players = {
[owner] = true
},
entities = {}
}
SetRoutingBucketEntityLockdownMode(
bucket,
'strict'
)
SetRoutingBucketPopulationEnabled(
bucket,
false
)
SetPlayerRoutingBucket(
owner,
bucket
)
return bucket
end
RegisterNetEvent(
'mission:create',
function()
local src =
source
local currentBucket =
GetPlayerRoutingBucket(
src
)
if currentBucket ~= 0 then
return
end
local bucket =
createInstance(src)
local ped =
GetPlayerPed(src)
if ped == 0 then
return
end
local coords =
GetEntityCoords(ped)
local vehicle =
CreateVehicleServerSetter(
joaat('sultan'),
'automobile',
coords.x + 5.0,
coords.y,
coords.z,
0.0
)
if vehicle ~= 0 then
SetEntityRoutingBucket(
vehicle,
bucket
)
SetEntityOrphanMode(
vehicle,
2
)
instances[bucket]
.entities[vehicle] =
true
end
end
)
ออกจาก Mission
RegisterNetEvent(
'mission:leave',
function()
local src =
source
local bucket =
GetPlayerRoutingBucket(
src
)
local instance =
instances[bucket]
if not instance then
return
end
instance.players[src] =
nil
SetPlayerRoutingBucket(
src,
0
)
local hasPlayers =
next(instance.players)
~= nil
if not hasPlayers then
for entity in pairs(
instance.entities
) do
if DoesEntityExist(
entity
) then
DeleteEntity(
entity
)
end
end
instances[bucket] =
nil
end
end
)
Concept คือ
Player
↓
Server Validate
↓
Allocate Bucket
↓
Configure Lockdown
↓
Disable Population
↓
Move Player
↓
Create Mission Entity
↓
Move Entity เข้า Bucket
↓
Mission
↓
Player Leave
↓
Bucket 0
↓
Cleanup
นี่เป็นพื้นฐานที่สามารถต่อยอดไปสู่ Party Instance ได้
คำถามที่พบบ่อยเกี่ยวกับ FiveM Routing Bucket
FiveM Routing Bucket คืออะไร
คือระบบ Dimension/Instance ของ OneSync สำหรับแยก Player และ Entities ออกเป็น Routing Context ต่างกันภายใน Server เดียว
Bucket 0 คืออะไร
โดยทั่วไปใช้เป็น Main World และ Player มักกลับ Bucket 0 เมื่อออกจาก Instance
วิธีเปลี่ยน Player Bucket
ใช้
SetPlayerRoutingBucket(
playerId,
bucket
)
วิธีดู Player Bucket
ใช้
GetPlayerRoutingBucket(
playerId
)
วิธีเปลี่ยน Entity Bucket
ใช้
SetEntityRoutingBucket(
entity,
bucket
)
วิธีดู Entity Bucket
ใช้
GetEntityRoutingBucket(
entity
)
Player กับ Vehicle ควรอยู่ Bucket เดียวกันไหม
ถ้า Vehicle เป็นส่วนหนึ่งของ Instance เดียวกัน โดยทั่วไปควรจัดให้อยู่ Bucket เดียวกัน
Routing Bucket ใช้ทำ Mission Instance ได้ไหม
ได้ และเป็นหนึ่งใน Use Case หลัก
ใช้ทำ Party ได้ไหม
ได้
ใช้ทำ Lobby ได้ไหม
ได้
ใช้ทำ Character Selection ได้ไหม
ได้ และ Cfx.re ยกเป็น Use Case โดยตรง
ใช้ทำ Interior ได้ไหม
Cfx.re ระบุว่า Interior ไม่ใช่ Use Case ที่แนะนำสำหรับ Routing Bucket โดยทั่วไป
Routing Bucket แยก Database ไหม
ไม่
Routing Bucket แยก Lua Variables ไหม
ไม่
Routing Bucket แยก Event Broadcast ให้อัตโนมัติไหม
อย่าพึ่งสมมติแบบนั้น ควร Target Events เฉพาะ Players ใน Instance ของคุณ
Routing Bucket ต้องใช้ OneSync ไหม
ใช่ เป็น Feature ใน OneSync/State Awareness Architecture
ปิด NPC ใน Bucket ได้ไหม
ได้ด้วย
SetRoutingBucketPopulationEnabled(
bucket,
false
)
ป้องกัน Client Spawn Entity ใน Bucket ได้ไหม
ได้ด้วย Entity Lockdown Mode เช่น strict ตาม Requirement
strict คืออะไร
ไม่อนุญาตให้ Clients สร้าง Entities ใน Bucket นั้นตาม OneSync Lockdown Policy
Player เลือก Bucket เองควรไหม
ไม่ควรสำหรับ Instance ที่มี Security/Privacy Server ควร Validate แล้วเป็นผู้กำหนด Bucket
มี Event ตอน Player เปลี่ยน Bucket ไหม
มี onPlayerBucketChange
มี Event ตอน Entity เปลี่ยน Bucket ไหม
มี onEntityBucketChange
Routing Bucket มีผลกับ Performance ไหม
แต่ละ Bucket มี Memory Cost จึงไม่ควรสร้างจำนวนมากโดยไม่มีเหตุผลและ Lifecycle
สรุป FiveM Routing Bucket คืออะไร
FiveM Routing Bucket คือระบบ Instance หรือ Dimension ของ OneSync ที่ใช้แยก Player และ Entity ออกเป็น Routing Context คนละชุดภายใน FXServer เดียว
ตัวอย่าง
Bucket 0
→ Main World
Bucket 101
→ Party Mission A
Bucket 102
→ Party Mission B
Bucket 500
→ Character Selection
Player เปลี่ยน Bucket ด้วย
SetPlayerRoutingBucket(
playerId,
bucket
)
Entity เปลี่ยนด้วย
SetEntityRoutingBucket(
entity,
bucket
)
และสามารถตรวจด้วย
GetPlayerRoutingBucket(...)
GetEntityRoutingBucket(...)
สิ่งสำคัญคืออย่าย้ายเฉพาะ Player แต่ลืม Mission Vehicles, Peds และ Objects เพราะ Entities ที่อยู่ Bucket อื่นจะไม่ได้อยู่ Routing Context เดียวกัน
สำหรับ Bucket ที่ต้องการควบคุมเข้มงวด ยังสามารถใช้
SetRoutingBucketEntityLockdownMode(
bucket,
'strict'
)
และ
SetRoutingBucketPopulationEnabled(
bucket,
false
)
เพื่อควบคุม Client Entity Creation และ Population ตาม Requirement
แต่ Routing Bucket ไม่ใช่คำตอบสำหรับทุกสิ่ง Cfx.re ระบุชัดว่า Interior ปกติไม่ใช่ Use Case ที่แนะนำสำหรับ Routing Buckets และทุก Bucket ยังมี Memory Cost จึงควรสร้างเท่าที่จำเป็นพร้อม Cleanup Lifecycle ที่ชัดเจน
สำหรับผู้ที่เรียน FiveM Developer กับ comsiam ให้จำว่า Routing Bucket ไม่ใช่แค่ “เลขห้อง” แต่เป็นส่วนหนึ่งของ OneSync Networking Architecture ซึ่ง Player, Vehicle, Ped, Object, Scope, Population และ Entity Security ล้วนได้รับผลจากการจัด Bucket
และหลักสำคัญจาก comsiam คือ Client ควรขอเข้า Session หรือ Mission ส่วน Server เป็นผู้ตัดสินว่าจะนำ Player ไป Bucket ใด ไม่ควรเปิด Network Event ที่ให้ Client ส่ง Bucket ID แล้ว Server ย้ายตามทันที
หัวข้อถัดไปคือ วิธีใช้ Routing Bucket ทำ Instance หรือ Dimension ใน FiveM ซึ่งจะนำพื้นฐานทั้งหมดนี้ไปสร้างระบบจริง ตั้งแต่ Bucket Allocator, Party Instance, การย้าย Player/Entity, การกลับ Bucket 0 ไปจนถึง Cleanup เมื่อ Instance ไม่มีผู้เล่นเหลือ
Comments
Post a Comment