FiveM playerDropped คืออะไร? วิธีตรวจผู้เล่นออก Server, เก็บเหตุผล Disconnect และล้าง Session
FiveM playerDropped คือ Server Event ที่ถูกเรียกเมื่อผู้เล่นหลุดหรือออกจาก Server โดย Cfx.re ระบุว่า Event นี้ให้ข้อมูลสำคัญ ได้แก่ source, reason, resourceName และ clientDropReason ซึ่งสามารถนำไปใช้สำหรับล้าง Session, บันทึก Log, ปลดข้อมูลชั่วคราว และตรวจสาเหตุการ Disconnect ได้.
สำหรับ Developer ที่มี Resource เก็บข้อมูลผู้เล่นไว้ใน Memory การเข้าใจ playerDropped สำคัญมาก เพราะถ้าสร้างข้อมูลตอน playerJoining แต่ไม่ล้างตอน Player ออก อาจทำให้ Session State เก่าค้างอยู่ใน Resource
Meta SEO
Meta Title: FiveM playerDropped คืออะไร? วิธีตรวจ Player Disconnect และล้าง Session
Meta Description: อธิบาย FiveM playerDropped แบบละเอียด source, reason, resourceName, clientDropReason ต่างกันอย่างไร วิธีเก็บ Disconnect Log และ Cleanup Player Session
Focus Keyword: FiveM playerDropped
Related Keywords: FiveM player disconnect, FiveM playerDropped event, FiveM disconnect reason, clientDropReason, FiveM session cleanup, FiveM server events
สารบัญ
① FiveM playerDropped คืออะไร
playerDropped เป็น Core Server Event ที่ถูกเรียกเมื่อ Player หลุดออกจาก Server และไม่ต้องติดตั้ง Resource เพิ่มเพื่อให้ Event นี้มีอยู่.
รูปแบบ Lua พื้นฐาน:
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
local src = source
print(('Player %s disconnected'):format(src))
end)
② playerDropped ทำงานฝั่งไหน
เป็น Server-side Event
ดังนั้น Handler ควรอยู่ในไฟล์ที่ถูกกำหนดเป็น server_script หรือ server_scripts ของ Resource
Cfx.re จัด playerDropped อยู่ในกลุ่ม Core Server Events.
③ playerDropped ทำงานตอนไหน
ลำดับเชิงแนวคิด:
Player Connecting
↓
playerConnecting
↓
playerJoining
↓
Player เล่นใน Server
↓
Player Disconnect
↓
playerDropped
จุดประสงค์หลักของ playerDropped คือแจ้ง Resource ฝั่ง Server ว่า Player Connection นั้นสิ้นสุดลงแล้ว.
④ playerDropped ใช้ทำอะไรได้บ้าง
งานที่เหมาะ เช่น:
ล้าง Session State
ลบ Player จาก Cache
บันทึก Disconnect Log
เก็บเวลาที่ Player ออก
ปลด Temporary State
แจ้ง Resource อื่นในระบบของ Server
วิเคราะห์ประเภท Disconnect
โดย Event มีข้อมูล Player และสาเหตุ Disconnect ให้ Resource ใช้งานโดยตรง.
⑤ playerDropped มี Parameters อะไร
Documentation ปัจจุบันระบุ:
reason
resourceName
clientDropReason
และ source หมายถึง Player ที่ Disconnect.
รูปแบบ:
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
local src = source
end)
⑥ Parameter ทั้งหมดจำง่ายอย่างไร
source
= ใครออก
reason
= ข้อความเหตุผล
resourceName
= Resource ที่ Event ถูก Dispatch จาก
clientDropReason
= รหัส Internal Drop Reason
ความหมายตรงตาม Parameters ที่ Cfx.re ระบุไว้สำหรับ playerDropped.
⑦ source ใน playerDropped คืออะไร
Cfx.re ระบุว่า source คือ Player ที่ Disconnect.
ใน Lua ควรเก็บ:
local src = source
ไว้ช่วงต้นของ Handler หากจะนำค่าไปใช้ต่อ
⑧ source เป็น Persistent Player ID หรือไม่
ไม่ควรใช้ source เป็น Account ID ถาวร
source ใช้ระบุ Player Connection ใน Session ของ Server ส่วน Persistent Identity ควรใช้ Identifier ที่เหมาะสม เช่น license, license2 หรือ fivem ตาม Architecture ของ Resource. Cfx.re แยก Player ID ออกจาก Provider Identifiers อย่างชัดเจน.
⑨ ทำไมต้องล้างข้อมูลที่ผูกกับ source
สมมติ Resource มี:
local sessions = {}
sessions[source] = {
character = 10,
busy = true
}
เมื่อ Player ออก หากไม่ล้าง:
sessions[source] = nil
ข้อมูล Session เดิมจะยังอยู่ใน Table ของ Resource
ดังนั้น Resource ที่สร้าง Runtime State ต่อ Player ควรมี Cleanup Strategy ตอน playerDropped
⑩ ตัวอย่าง Cleanup Session
local sessions = {}
AddEventHandler('playerDropped', function()
local src = source
sessions[src] = nil
end)
นี่เป็นหนึ่งในรูปแบบพื้นฐานที่สุดสำหรับ Resource ที่เก็บ State โดยอ้าง Server ID
⑪ ใช้คู่กับ playerJoining ได้อย่างไร
ตัวอย่าง:
local sessions = {}
AddEventHandler('playerJoining', function()
local src = source
sessions[src] = {
connected = true,
joinedAt = os.time()
}
end)
AddEventHandler('playerDropped', function()
local src = source
sessions[src] = nil
end)
แนวคิดคือ:
playerJoining
→ สร้าง Session
playerDropped
→ ล้าง Session
playerJoining และ playerDropped เป็น Server Events สำหรับคนละช่วงของ Player Lifecycle.
⑫ reason คืออะไร
reason เป็นข้อความที่อธิบายเหตุผลว่าทำไม Player จึง Disconnect.
ตัวอย่าง Log:
AddEventHandler('playerDropped', function(reason)
print(('Disconnect reason: %s'):format(reason))
end)
⑬ reason ใช้ทำ Disconnect Log ได้ไหม
ได้
ตัวอย่าง:
AddEventHandler('playerDropped', function(reason)
local src = source
local playerName = GetPlayerName(src) or 'Unknown'
print(('[DISCONNECT] %s | %s'):format(playerName, reason))
end)
Cfx.re เองมีตัวอย่าง Official ที่พิมพ์ Player Name และ Disconnect Reason ลง Server Console.
⑭ reason ใช้เป็น Business Logic หลักได้ไหม
สำหรับ Logic ที่ต้องแยกประเภท Disconnect อย่างเป็นระบบ ควรระวังการผูกระบบกับข้อความ reason เพียงอย่างเดียว เพราะ Event มี clientDropReason ซึ่งเป็นค่ารหัส Internal แยกต่างหากด้วย.
การเก็บทั้ง reason และ clientDropReason จะให้ข้อมูลสำหรับวิเคราะห์ได้ดีกว่าเก็บข้อความอย่างเดียว
⑮ resourceName คืออะไร
Cfx.re ระบุว่า resourceName คือ Resource ที่ Event ถูก Dispatch จาก.
ตัวอย่าง:
AddEventHandler('playerDropped', function(reason, resourceName)
print(('Event resource: %s'):format(resourceName))
end)
⑯ resourceName คือ Resource ที่ทำให้ Player หลุดเสมอไหม
ไม่ควรตีความแบบนั้น
ความหมายตาม Documentation คือ Resource ที่ Event ถูก Dispatch จาก ไม่ได้ระบุว่า Parameter นี้คือ “Script ที่เป็นต้นเหตุของ Disconnect” เสมอไป.
ดังนั้นอย่าเห็นชื่อ Resource แล้วสรุปทันทีว่า Resource นั้นเป็นตัวทำให้ Player หลุด
⑰ resourceName ของ Internal Drop อาจเป็นอะไร
Source Code ปัจจุบันของ Cfx.re กำหนดชื่อ Internal Resources สำหรับ Drop Context เช่น:
__cfx_internal:client
__cfx_internal:server
__cfx_internal:server_onesync
ตามประเภท Internal Drop ที่ระบบจัดการ.
ค่าจริงควรถูก Log แล้วตรวจตาม Version ของ Server ที่ใช้งาน
⑱ clientDropReason คืออะไร
Cfx.re ระบุว่า clientDropReason เป็น Unsigned Integer ซึ่งแทน Internal Reason ของการ Dispatch playerDropped Event.
ตัวอย่าง:
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
print(('Drop code: %s'):format(clientDropReason))
end)
⑲ clientDropReason มีประโยชน์อะไร
เหมาะกับการเก็บข้อมูล Disconnect แบบ Structured มากขึ้น เช่น:
Player
Reason Text
Resource Name
Drop Reason Code
Timestamp
เนื่องจาก Cfx.re แยก clientDropReason ออกจากข้อความ reason โดยตรง.
⑳ ClientDropReason ปัจจุบันมีประเภทอะไร
Source Code ปัจจุบันของ Cfx.re ระบุประเภท เช่น:
Resource เป็นผู้ Drop Client
Client Initiated Disconnect
Server Initiated Disconnect
Client ถูกแทนที่ด้วย Connection GUID เดียวกัน
Connection Timeout
Connection Timeout ขณะมี Pending Commands
Server Shutdown
State Bag Rate Limit
Net Event Rate Limit
Latent Net Event Rate Limit
Command Rate Limit
OneSync Missed Frames มากเกินไป
รายการเหล่านี้มาจาก ClientDropReasons.h ใน Source Repository ปัจจุบันของ Cfx.re.
㉑ clientDropReason เป็นเลขอะไรบ้าง
Enum ปัจจุบันเริ่มต้นด้วย:
RESOURCE = 1
CLIENT
SERVER
CLIENT_REPLACED
CLIENT_CONNECTION_TIMED_OUT
...
โดยค่าถัดไปเป็น Enum ต่อเนื่องตาม Source Code ปัจจุบัน.
สำหรับ Resource Production ควรอ้าง Enum ปัจจุบันแทน Hard-code Mapping จาก Tutorial เก่าที่อาจล้าสมัย
㉒ Timeout ตรวจได้ไหม
ใน ClientDropReasons.h ปัจจุบันมีประเภทสำหรับ Connection Timeout รวมทั้ง Timeout ที่มี Pending Commands.
ดังนั้นระบบ Logging สามารถเก็บ clientDropReason เพื่อช่วยแยก Timeout ออกจาก Disconnect บางประเภทได้
㉓ Server Shutdown แยกได้ไหม
ได้ในระดับ Internal Drop Reason ปัจจุบัน เพราะ Enum มี SERVER_SHUTDOWN.
มีประโยชน์เมื่อวิเคราะห์ Log ว่า Player ออกเองหรือ Server กำลัง Shutdown
㉔ Client ออกจากเกมแยกได้ไหม
Source Enum ปัจจุบันมี CLIENT สำหรับ Client-initiated Disconnect.
แต่การนำไปใช้กับระบบจริงควรบันทึกทั้ง Code และ Reason ที่ Event ส่งมา เพื่อมี Context เพิ่มเติม
㉕ Server เป็นฝ่าย Drop Player แยกได้ไหม
Enum ปัจจุบันมี SERVER สำหรับ Server-initiated Disconnect.
จึงสามารถใช้เป็นข้อมูลประกอบระบบ Audit/Monitoring ได้
㉖ Client Replaced คืออะไร
Source Code ระบุ CLIENT_REPLACED สำหรับกรณี Client ที่มี GUID เดียวกันเชื่อมต่อและ Connection ใหม่แทนที่ Client เดิม.
นี่เป็น Internal Reason ที่แตกต่างจาก Disconnect ปกติ
㉗ OneSync มี Drop Reason ของตัวเองไหม
Source Enum ปัจจุบันมี:
ONE_SYNC_TOO_MANY_MISSED_FRAMES
สำหรับกรณี OneSync มี Missed Frames มากเกินไป.
ถ้าพบประเภทนี้ซ้ำจำนวนมาก ควรวิเคราะห์ Server/Network/Performance ต่อ ไม่ควรสรุปว่าเป็นปัญหา Player เพียงอย่างเดียว
㉘ Rate Limit มี Drop Reason หรือไม่
Source Code ปัจจุบันมีเหตุผลสำหรับ:
STATE_BAG_RATE_LIMIT
NET_EVENT_RATE_LIMIT
LATENT_NET_EVENT_RATE_LIMIT
COMMAND_RATE_LIMIT
Developer ที่ทำ Monitoring จึงสามารถแยกกลุ่ม Drop เหล่านี้ออกจาก Timeout หรือ Client Quit ได้
㉙ playerDropped ควรล้างอะไรบ้าง
ขึ้นกับ Resource แต่ตัวอย่าง State ที่มักต้องตรวจ ได้แก่:
Session Table
Player Cache
Temporary Flags
Pending Actions
Per-player Timers
Server-side State ที่สร้างชั่วคราว
ควรล้างเฉพาะข้อมูลที่ Resource ของคุณเป็นเจ้าของ ไม่ควรให้ Resource หนึ่งไปลบ State ของอีก Resource แบบสุ่ม
㉚ ตัวอย่างล้าง Player Cache
local playerCache = {}
AddEventHandler('playerDropped', function()
local src = source
playerCache[src] = nil
end)
Resource ที่ใช้ Server ID เป็น Key สำหรับ Runtime Cache ควรมีจุด Cleanup เมื่อ Connection จบ
㉛ ตัวอย่างล้างหลาย Table
local sessions = {}
local cooldowns = {}
local temporaryJobs = {}
AddEventHandler('playerDropped', function()
local src = source
sessions[src] = nil
cooldowns[src] = nil
temporaryJobs[src] = nil
end)
อย่าลืมว่าข้อมูลถาวรใน Database และ Runtime Cache เป็นคนละเรื่อง
㉜ ควร Save Database ตอน playerDropped ไหม
ทำได้ตาม Architecture แต่ไม่ควรพึ่ง playerDropped เป็นจุดเดียวในการรักษาข้อมูลสำคัญ
ระบบข้อมูลถาวรควรมี Strategy ที่เหมาะสม เช่น Save ตามเหตุการณ์สำคัญหรือ Transaction ที่ระบบกำหนดไว้ด้วย
playerDropped เหมาะเป็นหนึ่งใน Lifecycle Hooks สำหรับ Cleanup/Finalization เมื่อ Player Connection จบ
㉝ อย่า Save ข้อมูลก้อนใหญ่ทุกอย่างแบบซ้ำซ้อน
หาก Framework มีระบบ Save Player Data อยู่แล้ว Resource เพิ่มเติมไม่ควร Query/Saveข้อมูลชุดเดิมซ้ำโดยไม่จำเป็น
ให้ตรวจ Framework Lifecycle ก่อนเพิ่ม Logic ใน playerDropped
㉞ Async Database ใน playerDropped ต้องระวังอะไร
ถ้า Resource ทำงาน Async ให้เก็บข้อมูลที่ต้องใช้ไว้ใน Local Variables ก่อนเริ่ม Callback เช่น:
AddEventHandler('playerDropped', function(reason)
local src = source
local cachedData = sessions[src]
sessions[src] = nil
if cachedData then
-- ส่งข้อมูลที่จำเป็นไปยังระบบบันทึก
end
end)
แนวคิดคือไม่พึ่ง State ของ Player ที่อาจถูก Cleanup ไปแล้วหลัง Callback ทำงาน
㉟ ตัวอย่าง Disconnect Log แบบครบ
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
local src = source
local name = GetPlayerName(src) or 'Unknown'
print((
'[DROP] Player=%s Source=%s Reason=%s Resource=%s Code=%s'
):format(
name,
src,
reason,
resourceName,
clientDropReason
))
end)
Parameters ทั้งสี่ส่วนตรงกับข้อมูลที่ Cfx.re ระบุสำหรับ playerDropped.
㊱ ควรเก็บ Timestamp ด้วยไหม
ถ้าทำระบบ Troubleshooting การมี Timestamp ช่วยให้เทียบ Disconnect กับ:
Script Error
Resource Restart
Server Restart
Network Incident
ได้ง่ายขึ้น
ตัวอย่าง:
local disconnectedAt = os.time()
㊲ ควรเก็บ Player Name อย่างเดียวไหม
ไม่ควรใช้ชื่อเป็น Identity หลัก เพราะชื่อเป็นข้อมูลแสดงผล
หากระบบต้อง Mapping กับ Account ให้ใช้ Identifier ที่เหมาะสม โดย GetPlayerIdentifiers() สามารถคืน license, license2, fivem, steam, discord และ ip ตามที่ Player มีอยู่.
㊳ ใช้ Identifier ใน playerDropped ได้ไหม
เมื่อ Event ทำงาน สามารถนำ Player ID ไปใช้กับ Identifier APIs ตาม Context ที่ยังรองรับในช่วง Event
แต่แนวทางที่แข็งแรงกว่าสำหรับระบบสำคัญคือ Cache Persistent Identifier ตั้งแต่ตอน Player Connect/Join แล้วใช้ Cache นั้นตอน Cleanup
Cfx.re ระบุว่า GetPlayerIdentifiers(player) คืนรายการ Identifiers ของ Player และเหมาะมากกับ playerConnecting.
㊴ ตัวอย่าง Cache License ตั้งแต่ Connecting
local playerLicenses = {}
AddEventHandler('playerConnecting', function()
local src = source
for _, identifier in ipairs(GetPlayerIdentifiers(src)) do
if identifier:sub(1, 8) == 'license:' then
playerLicenses[src] = identifier
break
end
end
end)
จากนั้น Architecture จริงอาจต้อง Mapping Temporary ID ไป Final Player ID ใน playerJoining ก่อนใช้ต่อ เพราะ source ใน playerConnecting เป็น Temporary Player ID.
㊵ อย่าเก็บ IP ใน Public Disconnect Log
ip เป็นหนึ่งใน Identifier Types ที่ Cfx.re สามารถคืนได้.
สำหรับ Logs ที่เปิดให้ผู้ใช้ทั่วไปเห็น ควรหลีกเลี่ยงการเผยแพร่ข้อมูล Network ของ Player โดยไม่จำเป็น
㊶ Player Identifier หายหลัง Disconnect ทำอย่างไร
ถ้าระบบต้องใช้ Identifier เพื่อ Finalize Session อย่างแน่นอน วิธีที่ควบคุมได้กว่าคือเก็บ Identifier ที่ต้องการไว้ตั้งแต่ Player Connect/Join ใน Server-side Cache
แล้วตอน playerDropped ใช้ Cache ดังกล่าวก่อนลบ
ตัวอย่าง:
local players = {}
-- หลัง Player พร้อม
players[src] = {
license = license
}
-- ตอนออก
local data = players[src]
players[src] = nil
㊷ playerDropped ไม่ทำงาน แก้อย่างไร
ตรวจตามลำดับ:
Handler อยู่ Server Script หรือไม่
Event Name คือ
playerDroppedหรือไม่Resource Start อยู่หรือไม่
Console มี Script Error หรือไม่
Resource ถูก Restart ระหว่างทดสอบหรือไม่
Player Disconnect จาก Server จริงหรือไม่
playerDropped เป็น Core Server Event ชื่อดังกล่าวโดยตรง.
㊸ Event Name ที่ถูกต้อง
ใช้:
playerDropped
ไม่ใช่:
playerDrop
playerDisconnected
onPlayerDropped
Cfx.re ใช้ชื่อ playerDropped ใน Core Event List.
㊹ playerDropped ทำงานแต่ Cache ไม่ถูกลบ
ตรวจว่าใช้ Key เดียวกันหรือไม่
ตัวอย่างสร้าง:
sessions[tostring(src)] = {}
แต่ตอนลบ:
sessions[src] = nil
นี่เป็นคนละ Key เพราะอันหนึ่งเป็น String และอีกอันเป็น Number
ให้ใช้ Data Type ให้สม่ำเสมอ
㊺ Player ออกแล้วข้อมูล Character ยังอยู่
แยกก่อนว่าเป็น:
Runtime Cache
ควรถูก Cleanup ตาม Resource
Persistent Database
อาจตั้งใจให้ข้อมูลยังอยู่เพื่อ Player กลับมาเล่นภายหลัง
อย่าลบ Database Character เพราะคิดว่า playerDropped หมายถึง Player Account ต้องถูกลบ
㊻ Disconnect Log ขึ้น Unknown Name
หากต้องการ Log ที่เชื่อถือได้มากขึ้น สามารถ Cache Player Name/Identifier ก่อน Disconnect และใช้ค่าที่ Cache ไว้เมื่อ Event ทำงาน
การออกแบบแบบนี้ยังช่วยให้ Log เชื่อมกับ Persistent Identity ได้ดีกว่าพึ่ง Display Name อย่างเดียว
㊼ Resource Restart ทำให้เกิด Cleanup แบบเดียวกับ Player Drop ไหม
ไม่ควรสมมติว่าเหมือนกัน
FiveM มี Events แยกสำหรับ Resource Lifecycle เช่น onResourceStop และ Player Lifecycle เช่น playerDropped.
Resource ที่มี State สำคัญควรพิจารณา Cleanup ทั้งสอง Scenario แยกกัน
㊽ Server Shutdown ควร Save ข้อมูลอย่างไร
clientDropReason ปัจจุบันมีประเภท SERVER_SHUTDOWN สำหรับ Player Drop ที่เกิดจาก Server Shutdown.
แต่ระบบข้อมูลสำคัญไม่ควรพึ่ง Player Drop อย่างเดียว ควรมี Resource/Server Shutdown Strategy ตาม Framework ที่ใช้งานด้วย
㊾ วิเคราะห์ Player หลุดบ่อยด้วย playerDropped ได้ไหม
ได้ในฐานะข้อมูล Server-side เช่นเก็บ:
Timestamp
Player Identifier
Reason
clientDropReason
Resource Name
แล้ววิเคราะห์จำนวน Timeout หรือ Drop Types
อย่างไรก็ตาม playerDropped บอกเหตุผลที่ Event รายงาน ไม่ได้พิสูจน์สาเหตุ Root Cause ของ Network/Client ทุกกรณีโดยตัวมันเอง
㊿ Checklist FiveM playerDropped
ก่อนใช้งาน Production ตรวจว่า:
Handler อยู่ Server Side
ใช้ Event Name ถูก
เก็บ
sourceก่อนใช้ต่อเข้าใจ
reasonเข้าใจ
resourceNameเก็บ
clientDropReasonหากต้องวิเคราะห์ไม่ใช้ Server ID เป็น Persistent Account ID
Cleanup Session Cache
Cleanup Per-player Timers
Cleanup Temporary Flags
ไม่ลบข้อมูลถาวรโดยไม่จำเป็น
ไม่เปิดเผย IP ใน Public Logs
ใช้ Persistent Identifier เมื่อจำเป็น
Cache Identifier ล่วงหน้าหากระบบต้องใช้แน่นอน
ทดสอบ Player Quit
ทดสอบ Connection Timeout ใน Environment ที่เหมาะสม
ทดสอบ Server Restart
ทดสอบ Resource Restart
ตรวจ Console Error
ตรวจว่า Session เก่าไม่ค้าง
ตาราง Parameters ของ playerDropped
| ค่า | ความหมาย |
|---|---|
source | Player ที่ Disconnect |
reason | ข้อความเหตุผล Disconnect |
resourceName | Resource ที่ Event ถูก Dispatch จาก |
clientDropReason | Internal Drop Reason แบบ unsigned integer |
ข้อมูลตาม Documentation ปัจจุบันของ Cfx.re.
ตาราง ClientDropReason ที่ควรรู้
| ประเภท | ความหมายโดยย่อ |
|---|---|
RESOURCE | Resource Drop Client |
CLIENT | Client เริ่ม Disconnect |
SERVER | Server เริ่ม Disconnect |
CLIENT_REPLACED | Connection ใหม่แทน Client เดิม |
CLIENT_CONNECTION_TIMED_OUT | Connection Timeout |
SERVER_SHUTDOWN | Server Shutdown |
STATE_BAG_RATE_LIMIT | State Bag Rate Limit |
NET_EVENT_RATE_LIMIT | Net Event Rate Limit |
LATENT_NET_EVENT_RATE_LIMIT | Latent Event Rate Limit |
COMMAND_RATE_LIMIT | Command Rate Limit |
ONE_SYNC_TOO_MANY_MISSED_FRAMES | OneSync Missed Frames มากเกิน |
รายการนี้อิงจาก ClientDropReasons.h ปัจจุบันของ Cfx.re.
ตัวอย่าง playerDropped + Session Cleanup
local players = {}
AddEventHandler('playerJoining', function()
local src = source
players[src] = {
name = GetPlayerName(src),
joinedAt = os.time()
}
end)
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
local src = source
local player = players[src]
if player then
print((
'[DROP] %s | reason=%s | resource=%s | code=%s'
):format(
player.name or 'Unknown',
reason,
resourceName,
clientDropReason
))
end
players[src] = nil
end)
โครงสร้าง Parameter ของ playerDropped ตรงตาม API ปัจจุบันของ Cfx.re.
ตัวอย่างเก็บ Disconnect Statistics
local dropStats = {}
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
local code = tostring(clientDropReason)
dropStats[code] = (dropStats[code] or 0) + 1
print(('Drop code %s total: %s'):format(
code,
dropStats[code]
))
end)
แนวคิดนี้ใช้ clientDropReason ซึ่ง Cfx.re ระบุเป็น Internal Reason Code ของ Event.
FiveM playerDropped กับ playerJoining ต่างกันอย่างไร
จำง่ายๆ:
playerJoining
= Player ได้ NetID และกำลังเข้าสู่ Server
playerDropped
= Player Connection สิ้นสุด
ทั้งสองเป็น Player Lifecycle Events ฝั่ง Server แต่ใช้คนละช่วงของ Connection.
FiveM playerDropped กับ playerConnecting ต่างกันอย่างไร
playerConnecting ทำงานตอน Player กำลังเข้า Server และรองรับ Deferrals เพื่อรอ Database หรือ API ก่อนตัดสินใจ Connection.
playerDropped ทำงานตอน Player ออกจาก Server แล้ว.
สูตรคือ:
playerConnecting
→ ตรวจว่าจะให้เข้าไหม
playerJoining
→ Player ได้ NetID
playerDropped
→ Player ออกและ Cleanup
FiveM playerDropped reason ดูอย่างไร
รับ Parameter แรก:
AddEventHandler('playerDropped', function(reason)
print(reason)
end)
Cfx.re ระบุ reason เป็นข้อความเหตุผลที่ Player Disconnect.
FiveM playerDropped clientDropReason ดูอย่างไร
รับ Parameter ที่สาม:
AddEventHandler('playerDropped', function(reason, resourceName, clientDropReason)
print(clientDropReason)
end)
ค่าดังกล่าวเป็น unsigned integer สำหรับ Internal Drop Reason.
FiveM Player Timeout ตรวจอย่างไร
หากต้องการทำ Disconnect Analytics ให้เก็บ clientDropReason แล้วเปรียบเทียบกับ Enum ปัจจุบัน ซึ่งมี Reason สำหรับ Connection Timeout.
ควรเก็บ reason ประกอบด้วยเพื่อช่วย Troubleshoot
FiveM Player ออกแล้ว Session ไม่หาย
ตรวจ Resource ที่สร้าง Session ก่อน
ถ้ามี:
sessions[src] = data
ต้องมี Cleanup ที่สอดคล้อง เช่น:
sessions[src] = nil
ใน playerDropped หรือ Lifecycle ที่ Resource กำหนด
อย่าแก้ด้วยการ Restart FXServer ทุกครั้ง เพราะต้นเหตุคือ Resource State Management
FAQ FiveM playerDropped
FiveM playerDropped คืออะไร
เป็น Core Server Event ที่ถูกเรียกเมื่อ Player หลุดออกจาก Server.
playerDropped มี Parameters อะไรบ้าง
มี reason, resourceName, clientDropReason และสามารถใช้ source เพื่ออ้าง Player ที่ Disconnect.
reason คืออะไร
เป็นข้อความเหตุผลที่ Player Disconnect.
clientDropReason คืออะไร
เป็น unsigned integer ที่แทน Internal Reason สำหรับ Player Drop Event.
playerDropped ใช้ล้าง Session ได้ไหม
ได้ และเหมาะกับ Resource ที่สร้าง Runtime State โดยอ้าง Player source เพราะ Event เกิดเมื่อ Player Connection สิ้นสุด.
playerDropped ใช้ดู Timeout ได้ไหม
Source Enum ปัจจุบันของ Cfx.re มีเหตุผลสำหรับ Client Connection Timeout และ Timeout ที่มี Pending Commands.
resourceName คือ Resource ที่ทำ Player หลุดหรือไม่
ไม่ควรสรุปเช่นนั้นจาก Parameter นี้เพียงอย่างเดียว เพราะ Documentation ระบุว่า resourceName คือ Resource ที่ Event ถูก Dispatch จาก.
Player ID ใน playerDropped ใช้เป็น Database ID ได้ไหม
ไม่ควรใช้ source เป็น Persistent Account Identity ควรใช้ Provider Identifier ที่เหมาะสม เช่น License หรือ Cfx Identifier ตามระบบ Server.
ประเด็นสำคัญ
FiveM playerDropped คือ Event สำคัญสำหรับช่วง Player ออกจาก Server โดย Cfx.re ให้ข้อมูล source, reason, resourceName และ clientDropReason เพื่อให้ Resource รู้ว่าใคร Disconnect และระบบรายงานเหตุผลอย่างไร.
Resource ที่สร้าง Session หรือ Cache ด้วย Server ID ควร Cleanup State เมื่อ playerDropped เพื่อไม่ให้ข้อมูล Connection เก่าค้างอยู่ และต้องแยก Runtime State ออกจาก Persistent Player Data ให้ชัดเจน
สำหรับระบบ Logging ควรเก็บทั้ง Reason Text + clientDropReason + Timestamp + Persistent Identifier ที่จำเป็น มากกว่าพึ่ง Player Name หรือ Reason Text เพียงอย่างเดียว โดย Cfx.re มี Internal Drop Reasons แยกทั้ง Client Disconnect, Server Disconnect, Timeout, Server Shutdown, Rate Limits และ OneSync Missed Frames.
ในภาพรวม Player Lifecycle ที่ควรจำคือ playerConnecting → playerJoining → playerDropped โดย Connecting เหมาะกับการตรวจสิทธิ์ก่อนเข้า, Joining ใช้เมื่อได้รับ NetID แล้ว และ Dropped ใช้ Cleanup เมื่อ Connection จบ.
สำหรับผู้อ่าน comsiam ให้จำสูตร “Joining = สร้าง Session, Dropped = ล้าง Session” และ comsiam แนะนำให้เก็บ clientDropReason เพิ่มจากข้อความ reason หากต้องการวิเคราะห์ปัญหาผู้เล่นหลุด เพราะช่วยแยกประเภท Disconnect ได้เป็นระบบมากขึ้น
Comments
Post a Comment