FiveM TriggerServerEvent และ TriggerClientEvent คืออะไร? วิธีส่งข้อมูลระหว่าง Client กับ Server อย่างถูกต้อง

 FiveM TriggerServerEvent และ TriggerClientEvent คือหัวใจสำคัญของระบบ Network Events ที่ใช้ส่งข้อมูลระหว่าง Client และ Server ใน FiveM โดย TriggerServerEvent ใช้ส่ง Event จาก Client → Server ส่วน TriggerClientEvent ใช้ส่ง Event จาก Server → Client ที่ระบุ หรือส่งไปยัง Client ทุกคนได้.

การเข้าใจระบบนี้สำคัญมากสำหรับ Developer เพราะระบบ Gameplay จำนวนมาก เช่น Inventory, Job, Garage, UI, Character และ Notification ล้วนต้องสื่อสารระหว่าง Client กับ Server แต่ Cfx.re เตือนชัดเจนว่า ข้อมูลที่ Client ส่งขึ้น Server ไม่ควรถูกเชื่อถือทันที และควรตรวจสอบข้อมูลสำคัญฝั่ง Server เสมอ.

Meta SEO

Meta Title: FiveM TriggerServerEvent และ TriggerClientEvent คืออะไร? วิธีใช้งาน Network Events

Meta Description: อธิบาย FiveM TriggerServerEvent, TriggerClientEvent, RegisterNetEvent และ AddEventHandler แบบละเอียด พร้อมตัวอย่าง Client Server และแนวทางตรวจข้อมูลอย่างปลอดภัย

Focus Keyword: FiveM TriggerServerEvent

Related Keywords: FiveM TriggerClientEvent, FiveM RegisterNetEvent, FiveM AddEventHandler, FiveM Network Events, FiveM Lua Events

สารบัญ

① TriggerServerEvent คืออะไร

TriggerServerEvent เป็น Function สำหรับเรียก Server Event จาก Client Script

Syntax:

TriggerServerEvent(eventName, ...)

Cfx.re ระบุว่า Function นี้ใช้ส่ง Event จาก Client ไปยัง Server พร้อม Arguments เพิ่มเติมได้.

ตัวอย่าง:

TriggerServerEvent('myResource:helloServer')

② ส่งข้อมูลพร้อม TriggerServerEvent ได้ไหม

ได้

ตัวอย่าง:

local message = 'Hello Server'

TriggerServerEvent('myResource:sendMessage', message)

Arguments ที่ส่งตามหลัง Event Name จะถูกส่งไปยัง Handler ฝั่ง Server ตามลำดับ.

③ ฝั่ง Server ต้องรับ Event อย่างไร

สำหรับ Lua สามารถใช้:

RegisterNetEvent('myResource:sendMessage', function(message)
    print(message)
end)

Cfx.re ระบุว่า RegisterNetEvent ใช้ Register Event สำหรับ Network Usage และสามารถใส่ Callback ลงไปได้โดยตรง.

④ ตัวอย่าง Client → Server แบบครบ

client.lua

RegisterCommand('hello', function()
    TriggerServerEvent('example:helloServer', 'Hello from client')
end, false)

server.lua

RegisterNetEvent('example:helloServer', function(message)
    local src = source

    print(('Player %s says: %s'):format(src, message))
end)

TriggerServerEvent ใช้ส่งจาก Client และฝั่ง Server ต้อง Register Network Event สำหรับรับ Event นั้น.

⑤ source ใน Server Event คืออะไร

เมื่อ Network Event ถูก Trigger จาก Player ค่า:

source

ฝั่ง Server ใช้อ้าง Player ที่ Trigger Event นั้น

Cfx.re Documentation ระบุว่าใน Server Event Handler ค่า source สามารถใช้อ้างผู้เล่นต้นทางของ Event ได้.

ตัวอย่าง:

RegisterNetEvent('example:test', function()
    local src = source

    print(('Event from player %s'):format(src))
end)

⑥ อย่าส่ง Player ID จาก Client ถ้า Server รู้ source อยู่แล้ว

ตัวอย่างที่ไม่จำเป็น:

TriggerServerEvent('example:test', GetPlayerServerId(PlayerId()))

ถ้า Server ต้องการเพียงรู้ว่า ใครเป็นผู้ Trigger Event ก็สามารถใช้ source ได้

ตัวอย่าง:

RegisterNetEvent('example:test', function()
    local src = source
end)

ช่วยลดข้อมูลที่ต้องส่งผ่าน Network

⑦ TriggerServerEvent ควรส่งข้อมูลให้น้อยที่สุด

Cfx.re แนะนำให้ลดข้อมูลที่ส่งผ่าน Events เพราะการส่งและรับข้อมูลมี Serialization Overhead และควรใช้ข้อมูลที่เรียบง่ายและมีขนาดเท่าที่จำเป็น.

ดังนั้นถ้าต้องการเพียง:

vehicleId = 25

ไม่ควรส่ง Table ขนาดใหญ่ที่มีข้อมูลรถทั้งหมดหาก Server สามารถค้นข้อมูลจาก ID ได้เอง

⑧ TriggerClientEvent คืออะไร

TriggerClientEvent ใช้ส่ง Event จาก Server → Client

Syntax:

TriggerClientEvent(eventName, playerId, ...)

โดย Parameter ที่สองคือ Player ID เป้าหมาย.

ตัวอย่าง:

TriggerClientEvent('example:notify', playerId, 'Hello')

⑨ Client รับ TriggerClientEvent อย่างไร

ฝั่ง Client:

RegisterNetEvent('example:notify', function(message)
    print(message)
end)

ฝั่ง Server:

TriggerClientEvent('example:notify', playerId, 'Hello Client')

RegisterNetEvent ใช้ Register Event ให้สามารถถูก Trigger ข้าม Network Context ได้.

⑩ ตัวอย่าง Server → Client แบบครบ

server.lua

RegisterCommand('sendhello', function(source)
    if source == 0 then
        return
    end

    TriggerClientEvent(
        'example:helloClient',
        source,
        'Hello from server'
    )
end, false)

client.lua

RegisterNetEvent('example:helloClient', function(message)
    print(message)
end)

TriggerClientEvent ต้องกำหนด Player เป้าหมายสำหรับ Lua.

⑪ ส่ง TriggerClientEvent ให้ทุกคนอย่างไร

Cfx.re ระบุว่าสามารถใช้:

TriggerClientEvent('eventName', -1, ...)

โดย -1 หมายถึงส่งให้ Clients ที่ Connected ทั้งหมด.

ตัวอย่าง:

TriggerClientEvent(
    'example:announcement',
    -1,
    'Server restart soon'
)

⑫ อย่า Broadcast ทุกอย่างด้วย -1

ถึงแม้ -1 จะสะดวก แต่ถ้าข้อมูลต้องส่งให้ Player คนเดียวควรกำหนด Target เฉพาะ

ตัวอย่าง:

TriggerClientEvent('garage:open', source, vehicleData)

แทน:

TriggerClientEvent('garage:open', -1, vehicleData)

เพราะการส่งให้ทุกคนโดยไม่จำเป็นเพิ่ม Network Traffic และอาจเปิดเผยข้อมูล Gameplay แก่ Clients ที่ไม่ต้องใช้

⑬ RegisterNetEvent คืออะไร

RegisterNetEvent ใช้ Mark Event สำหรับ Network Use

Cfx.re ระบุว่า Event ที่ต้อง Trigger ระหว่าง Client และ Server ต้อง Register เป็น Network Event ก่อนสำหรับ Lua/JS.

ตัวอย่าง:

RegisterNetEvent('example:test', function()
    print('Event fired')
end)

⑭ RegisterNetEvent เขียนได้สองแบบ

แบบรวม Callback:

RegisterNetEvent('example:test', function(data)
    print(data)
end)

หรือแยก:

RegisterNetEvent('example:test')

AddEventHandler('example:test', function(data)
    print(data)
end)

Cfx.re รองรับทั้งสองรูปแบบ.

⑮ แบบไหนง่ายกว่าสำหรับมือใหม่

แบบนี้อ่านง่าย:

RegisterNetEvent('example:test', function(data)
    print(data)
end)

เพราะ Event Registration และ Handler อยู่ใกล้กัน

Cfx.re เองแสดงรูปแบบ Callback โดยตรงเป็นรูปแบบที่ใช้งานได้สำหรับ Network Event.

⑯ AddEventHandler คืออะไร

AddEventHandler ใช้เพิ่ม Handler ให้ Event

แต่ Cfx.re แนะนำว่า หาก Event ใช้งานเฉพาะ Context เดียวกัน เช่น Server → Server หรือ Client → Client ควรใช้ AddEventHandler แทนการ Register เป็น Network Event โดยไม่จำเป็น.

ตัวอย่าง Server-local Event:

AddEventHandler('example:internalEvent', function(data)
    print(data)
end)

⑰ Event ภายใน Server ไม่ต้อง RegisterNetEvent เสมอไป

ถ้า Event ถูก Trigger:

Server Resource → Server Resource

และไม่ต้องให้ Client Trigger

Cfx.re แนะนำใช้ AddEventHandler เพื่อให้ Event ไม่ถูก Networked โดยไม่จำเป็น.

นี่เป็นแนวคิดสำคัญมากสำหรับการออกแบบ Resource

⑱ TriggerEvent คืออะไร

TriggerEvent ใช้ Trigger Event ภายใน Context เดียวกัน

ตัวอย่าง:

TriggerEvent('example:internalEvent', 'hello')

Cfx.re ระบุว่า Local Events ฝั่ง Server → Server หรือ Client → Client ใช้ TriggerEvent.

⑲ TriggerEvent กับ TriggerServerEvent ต่างกันอย่างไร

TriggerEvent

Context เดียวกัน

Client → Client
Server → Server

TriggerServerEvent

Client → Server

Cfx.re แยก Local Events และ Server Network Events ออกจากกันโดยตรง.

⑳ TriggerClientEvent ใช้ทางไหน

Server → Client

และสามารถระบุ Player คนเดียวหรือ -1 เพื่อส่งให้ทุก Clients.

㉑ จำ Event Direction แบบง่าย

TriggerEvent
= ภายใน Context เดียวกัน

TriggerServerEvent
= Client → Server

TriggerClientEvent
= Server → Client

นี่เป็นพื้นฐานที่ควรจำก่อนเริ่มเขียน Resource ที่มี Client/Server Communication.

㉒ ตัวอย่าง Client ขอข้อมูลจาก Server

Client:

TriggerServerEvent('playerData:request')

Server:

RegisterNetEvent('playerData:request', function()
    local src = source

    local data = {
        name = GetPlayerName(src)
    }

    TriggerClientEvent('playerData:receive', src, data)
end)

Client:

RegisterNetEvent('playerData:receive', function(data)
    print(data.name)
end)

นี่เป็น Pattern:

Client Request
↓
Server Process
↓
Server Response
↓
Client Receive

โดยใช้ Network Events สองทิศทางตาม APIs ของ Cfx.re.

㉓ Event ไม่ใช่ Function Return แบบทันที

อย่าเขียน Architecture โดยคิดว่า:

local result = TriggerServerEvent(...)

แล้ว Server จะ Return ค่าให้ตัวแปรทันที

Network Events เป็น Event-driven Communication

หาก Client ต้องการข้อมูลกลับ ให้ Server Trigger Event กลับมา หรือใช้ Mechanism ของ Framework/Resource ที่ออกแบบเป็น Callback

㉔ ควรตั้งชื่อ Event อย่างไร

ชื่อที่ดีควรมี Prefix ของ Resource เช่น:

garage:requestVehicle
garage:receiveVehicle
inventory:useItem
character:loaded

ดีกว่า:

get
send
event1
test

เพราะ Server ที่มีหลาย Resources จะ Debug Event Names ได้ง่ายกว่า

㉕ ใช้ชื่อ Resource เป็น Prefix

ตัวอย่าง:

RegisterNetEvent('mygarage:requestVehicle', function(vehicleId)
end)

ช่วยลดโอกาสชื่อ Event ซ้ำกับ Resource อื่นและทำให้ Search Console/Code ได้ง่าย

㉖ ห้ามเชื่อข้อมูลจาก Client โดยตรง

Cfx.re ระบุชัดว่า ไม่ควรเชื่อข้อมูลจาก Client และควรตรวจข้อมูลที่ Client ส่งขึ้น Server ก่อนนำไปเปลี่ยน State สำคัญ.

ตัวอย่าง Client ส่ง:

TriggerServerEvent('shop:buyItem', itemId)

Server ควรตรวจอย่างน้อยว่า:

  • Item มีจริง

  • Player ซื้อ Item นี้ได้

  • Player มีเงินเพียงพอ

  • Quantity ถูกต้อง

  • Player มี Permission ที่จำเป็น

โดยข้อมูลสำคัญควรตรวจจาก Server-side State.

㉗ อย่าให้ Client กำหนดเงินที่จะได้รับ

รูปแบบที่ควรหลีกเลี่ยง:

TriggerServerEvent('job:reward', 1000000)

แล้ว Server ทำ:

RegisterNetEvent('job:reward', function(amount)
    GiveMoney(source, amount)
end)

เพราะ Server กำลังใช้ค่ารางวัลที่ Client เป็นผู้กำหนด

Cfx.re ยกตัวอย่างแนวคิดเดียวกันว่า Event ที่เกี่ยวข้องกับ Item/Reward ควรตรวจข้อมูลจากฝั่ง Server ไม่ใช่เชื่อ Input ของ Client.

㉘ ให้ Client ส่ง Action ไม่ใช่ Authority

แนวคิดที่ดีกว่า:

TriggerServerEvent('job:finish')

จากนั้น Server ตรวจ:

Player ทำ Job อยู่จริงไหม
↓
ถึงจุดส่งของจริงไหม
↓
มี Item ที่ต้องส่งหรือไม่
↓
Reward ที่ Server กำหนดคือเท่าไร
↓
จึงให้ Reward

Cfx.re แนะนำให้ตรวจ Player Money, Inventory, Position, Experience และ Permissions จาก Server-side Methods.

㉙ ตรวจ Permission ฝั่ง Server

หาก Event เป็น Admin Feature:

RegisterNetEvent('admin:action', function()
    local src = source

    if not IsAllowedAdmin(src) then
        return
    end

    -- ทำงาน
end)

ไม่ควรเชื่อค่าจาก Client เช่น:

isAdmin = true

Cfx.re ระบุว่า Permission และ Roles เป็นหนึ่งในข้อมูลที่ควรถูกตรวจจากฝั่ง Server.

㉚ ตรวจ Inventory ฝั่ง Server

Client สามารถบอกได้ว่า:

“ฉันต้องการใช้ Item X”

แต่ Server ควรตรวจว่า:

Player มี Item X จริงหรือไม่

ก่อนเปลี่ยน Inventory State

Cfx.re ยก Inventory Items เป็นหนึ่งในค่าที่ควร Validate Server-side.

㉛ ตรวจ Position ฝั่ง Serverเมื่อจำเป็น

ถ้า Event ต้องเกิดเฉพาะเมื่อ Player อยู่บริเวณหนึ่ง เช่นส่ง Job Item

Server ควรตรวจ Position ตาม Architecture ที่ใช้แทนเชื่อ Boolean จาก Client เช่น:

client says: nearDeliveryPoint = true

Cfx.re ระบุ Player Position เป็นตัวอย่างข้อมูลที่ควรตรวจใน Server Event Security.

㉜ Network Event ทุกตัวควร RegisterNetEvent ไหม

ไม่

Cfx.re แนะนำ:

ต้องข้าม Client ↔ Server

ใช้ RegisterNetEvent

Event อยู่ Context เดียวกัน

ใช้ AddEventHandler

เพื่อไม่ทำ Event เป็น Network Event โดยไม่จำเป็น.

㉝ RegisterNetEvent ไม่ได้ทำ Event ปลอดภัยเองทั้งหมด

RegisterNetEvent ทำให้ Event สามารถใช้ข้าม Network Context ได้ แต่ Developer ยังคงต้อง Validate Inputs และ Permissions เอง

Cfx.re ระบุว่าถึงแม้มีระบบ Anti-cheat ก็ควรเพิ่ม Server-side Checks ใน Network Events.

㉞ Client Event ก็ไม่ควรถือเป็นข้อมูลที่เชื่อถือได้

Client Code อยู่ฝั่งผู้เล่น ดังนั้น Logic สำคัญ เช่น:

  • เงิน

  • Inventory

  • Rewards

  • Permissions

  • Account State

ควรถูกตัดสินฝั่ง Server

Cfx.re ระบุว่า Client-side Checks สามารถมีประโยชน์ แต่ไม่ควรถูกใช้แทน Server-side Validation สำหรับข้อมูลสำคัญ.

㉟ TriggerLatentServerEvent คืออะไร

สำหรับข้อมูลขนาดใหญ่ Cfx.re แนะนำใช้ Latent Events

จาก Client → Server:

TriggerLatentServerEvent(
    'eventName',
    bps,
    data
)

Cfx.re ระบุว่า Latent Events เหมาะกับข้อมูลขนาดหลาย KB ขึ้นไป เพราะไม่ Block Network Channel แบบ Standard Event.

㊱ TriggerLatentClientEvent คืออะไร

เป็น Latent Event ฝั่ง:

Server → Client

รูปแบบ:

TriggerLatentClientEvent(
    'eventName',
    playerId,
    bps,
    data
)

เหมาะกับข้อมูลขนาดใหญ่ที่ไม่ควรถูกส่งรวดเดียวผ่าน Standard Network Event.

㊲ ทำไมข้อมูลใหญ่ไม่ควรใช้ TriggerClientEvent ปกติ

Cfx.re ระบุว่าการส่งข้อมูลขนาดใหญ่ผ่าน Standard Event สามารถ Block Network Channel และถ้า Block นานเกินไปอาจนำไปสู่ Client Timeout ได้.

ดังนั้นอย่าส่ง Tables ขนาดใหญ่มากผ่าน:

TriggerClientEvent(...)

โดยไม่พิจารณาขนาดข้อมูล

㊳ bps คืออะไร

Latent Event มี Parameter bps หรือ bytes per second

Cfx.re ระบุว่าหากตั้ง 0 หรือ -1 ระบบจะใช้ค่า Default ที่ 25,000 bytes per second.

ไม่ควรตั้งค่า Transfer Rate สูงมากโดยไม่เข้าใจผลต่อ Network/Performance

㊴ Standard หรือ Latent เลือกอย่างไร

ข้อมูลเล็ก

ใช้:

TriggerServerEvent
TriggerClientEvent

ข้อมูลหลาย KB หรือขนาดใหญ่

พิจารณา:

TriggerLatentServerEvent
TriggerLatentClientEvent

Cfx.re แนะนำแนวทางนี้โดยตรง.

㊵ TriggerServerEvent ไม่ทำงาน แก้อย่างไร

ตรวจ:

  1. client.lua ถูกโหลดหรือไม่

  2. Event Name ตรงกันหรือไม่

  3. Server Resource Start หรือไม่

  4. Server ใช้ RegisterNetEvent หรือไม่

  5. Console มี Error หรือไม่

  6. Parameters ตรงกันหรือไม่

Cfx.re ระบุว่า Lua Network Events ต้องถูก Register ก่อนจึงจะใช้งานข้าม Network Context ได้.

㊶ TriggerClientEvent ไม่ทำงาน แก้อย่างไร

ตรวจ:

  1. Player ID ถูกหรือไม่

  2. Client Resource Start หรือไม่

  3. Client Register Event แล้วหรือไม่

  4. Event Name ตรงกันหรือไม่

  5. Client F8 Console มี Error หรือไม่

TriggerClientEvent ต้องระบุ Client Target และ Client ต้องมี Network Event Handler ที่ตรงกัน.

㊷ Event Name ไม่ตรงกัน

Client:

TriggerServerEvent('garage:getVehicle')

Server:

RegisterNetEvent('garage:getVehicles', function()
end)

สองชื่อไม่ตรงกัน

getVehicle
getVehicles

Event จึงไม่เข้า Handler ที่ต้องการ

㊸ Parameter Order ไม่ตรงกัน

Client:

TriggerServerEvent(
    'example:test',
    vehicleId,
    plate
)

Server:

RegisterNetEvent('example:test', function(plate, vehicleId)
end)

ถึง Event จะ Trigger แต่ค่าถูกสลับตำแหน่ง

ควรใช้ Parameter Order ที่ชัดเจนและสอดคล้องกันทั้ง Client/Server

㊹ ใช้ print Debug Event

Client:

print('before TriggerServerEvent')

TriggerServerEvent('example:test', 123)

print('after TriggerServerEvent')

Server:

RegisterNetEvent('example:test', function(value)
    print(('event received: %s'):format(value))
end)

จากนั้นดู:

  • Client F8

  • txAdmin Server Console

เพื่อหา Stage ที่ Event หยุดทำงาน

㊺ Event Trigger ซ้ำหลายครั้ง

ตรวจว่า Code Trigger อยู่ใน:

  • Loop

  • Thread

  • Key Input

  • NUI Callback

  • Event Handler อื่น

และถูกเรียกมากกว่าหนึ่งครั้งหรือไม่

Network Event ที่ Trigger ซ้ำโดยไม่ตั้งใจสามารถสร้างทั้ง Logic Error และ Network Load เพิ่ม

㊻ อย่า Trigger Event ทุก Frame โดยไม่จำเป็น

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

CreateThread(function()
    while true do
        TriggerServerEvent('example:update')
        Wait(0)
    end
end)

เพราะกำลังส่ง Network Event ซ้ำอย่างต่อเนื่อง

ควรส่งเมื่อข้อมูลเปลี่ยนจริงหรือใช้ระบบ State/Sync ที่เหมาะกับข้อมูลนั้นแทน

㊼ Event ข้อมูลใหญ่ทำ Player หลุด

หาก Resource ส่ง Payload ขนาดใหญ่ผ่าน Standard Events Cfx.re ระบุว่า Network Channel สามารถถูก Block และอาจทำให้ Timeout ได้

ให้ตรวจ Payload และพิจารณา Latent Events สำหรับข้อมูลใหญ่.

㊽ Event ทำงานแต่ข้อมูล nil

ตรวจ:

  • Parameter ถูกส่งหรือไม่

  • Order ถูกหรือไม่

  • Key ใน Table ถูกหรือไม่

  • Serialization รองรับข้อมูลที่ส่งหรือไม่

  • Event Handler รับ Parameters ครบหรือไม่

และลด Payload ให้เหลือข้อมูลที่จำเป็นตามคำแนะนำของ Cfx.re.

㊾ Checklist FiveM Network Events

ก่อนใช้ Production ตรวจว่า:

  1. Event Direction ถูกต้อง

  2. Local Event ใช้ AddEventHandler

  3. Network Event ใช้ RegisterNetEvent

  4. Client → Server ใช้ TriggerServerEvent

  5. Server → Client ใช้ TriggerClientEvent

  6. ใช้ source ฝั่ง Server อย่างถูกต้อง

  7. ไม่ส่งข้อมูลเกินจำเป็น

  8. ไม่เชื่อ Client Input

  9. ตรวจ Money ฝั่ง Server

  10. ตรวจ Inventory ฝั่ง Server

  11. ตรวจ Permission ฝั่ง Server

  12. ตรวจ Position เมื่อจำเป็น

  13. Target Client ถูกต้อง

  14. ไม่ Broadcast ด้วย -1 โดยไม่จำเป็น

  15. Event Names มี Prefix

  16. Parameters ตรงกัน

  17. Payload ใหญ่ใช้ Latent Event เมื่อเหมาะสม

  18. Client F8 ไม่มี Error

  19. Server Console ไม่มี Error

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

㊿ ตาราง FiveM Event Functions ที่ควรรู้

Functionทิศทาง
TriggerEventContext เดียวกัน
TriggerServerEventClient → Server
TriggerClientEventServer → Client
RegisterNetEventRegister Network Event
AddEventHandlerListen Event
TriggerLatentServerEventClient → Server ข้อมูลใหญ่
TriggerLatentClientEventServer → Client ข้อมูลใหญ่

การแบ่ง Local, Network และ Latent Events นี้ตรงกับ Event Documentation ปัจจุบันของ Cfx.re.

ตัวอย่าง Request → Response ที่ถูกโครงสร้าง

client.lua

RegisterCommand('myname', function()
    TriggerServerEvent('example:requestName')
end, false)

RegisterNetEvent('example:receiveName', function(name)
    print(('Your name is %s'):format(name))
end)

server.lua

RegisterNetEvent('example:requestName', function()
    local src = source
    local name = GetPlayerName(src)

    TriggerClientEvent(
        'example:receiveName',
        src,
        name
    )
end)

นี่เป็น Pattern Client Request → Server Process → Client Response โดยใช้ APIs Network Events ของ FiveM.

ตัวอย่าง Event Validation ฝั่ง Server

Client:

TriggerServerEvent('shop:buy', 'water')

Server:

RegisterNetEvent('shop:buy', function(itemName)
    local src = source

    local item = ShopItems[itemName]

    if not item then
        return
    end

    local playerMoney = GetServerSideMoney(src)

    if playerMoney < item.price then
        return
    end

    RemoveServerSideMoney(src, item.price)
    GiveServerSideItem(src, itemName, 1)
end)

Functions ด้านเงินและ Item ในตัวอย่างเป็น Function สมมติ แต่หลักสำคัญคือ Price, Money และ Inventory Decision อยู่ฝั่ง Server ไม่ใช่รับค่าที่ Client อ้างมาโดยตรง ซึ่งตรงกับแนวทาง Security ของ Cfx.re.

FiveM TriggerServerEvent ไม่เข้า Server

ตรวจก่อนว่า Server มี:

RegisterNetEvent('eventName', function()
end)

และ Event Name ตรงกับ:

TriggerServerEvent('eventName')

สำหรับ Lua/JS Network Event ต้องถูก Register สำหรับ Network Usage.

FiveM TriggerClientEvent ไม่เข้า Client

Server:

TriggerClientEvent(
    'example:event',
    source,
    data
)

Client ต้องมี:

RegisterNetEvent('example:event', function(data)
end)

และ Target Player ID ต้องถูกต้อง.

FiveM TriggerClientEvent -1 คืออะไร

-1 หมายถึง Trigger Event ให้ Clients ที่ Connected ทั้งหมด สำหรับ Lua.

ตัวอย่าง:

TriggerClientEvent(
    'server:announcement',
    -1,
    'Hello everyone'
)

ควรใช้เฉพาะเมื่อทุก Client ต้องได้รับข้อมูลนั้นจริง

FiveM RegisterNetEvent กับ AddEventHandler ต่างกันอย่างไร

RegisterNetEvent ใช้เมื่อ Event ต้องข้าม Client/Server Network Context

ส่วน AddEventHandler เหมาะกับ Event ที่ใช้ภายใน Context เดียวกันและไม่ควรเปิดเป็น Network Event โดยไม่จำเป็น.

FiveM Network Event ข้อมูลเยอะทำอย่างไร

หาก Payload มีขนาดหลาย KB ขึ้นไป Cfx.re แนะนำ Latent Events เพื่อไม่ให้ข้อมูลก้อนใหญ่ Block Network Channel.

Client → Server:

TriggerLatentServerEvent(
    'example:largeData',
    25000,
    data
)

Server → Client:

TriggerLatentClientEvent(
    'example:largeData',
    targetPlayer,
    25000,
    data
)

FiveM Event ปลอดภัยอย่างไร

สูตรพื้นฐาน:

Client ขอ Action
↓
Server ตรวจ source
↓
Server ตรวจข้อมูลจริง
↓
Server ตรวจ Permission
↓
Server ตรวจ State
↓
Server ทำ Action
↓
Server ส่ง Result กลับ Client

Cfx.re แนะนำให้ Server ตรวจข้อมูลสำคัญ เช่น Money, Inventory, Position, Experience และ Permissions ด้วย Server-side Methods.

FAQ FiveM TriggerServerEvent และ TriggerClientEvent

TriggerServerEvent คืออะไร

ใช้ Trigger Event จาก Client ไปยัง Server พร้อมส่ง Parameters เพิ่มเติมได้.

TriggerClientEvent คืออะไร

ใช้ Trigger Event จาก Server ไปยัง Client ที่กำหนด และใน Lua สามารถใช้ -1 เพื่อส่งให้ Clients ทั้งหมด.

RegisterNetEvent คืออะไร

ใช้ Register Event สำหรับ Network Usage เพื่อให้สามารถ Trigger ข้าม Client/Server Context ได้.

TriggerEvent ต่างจาก TriggerServerEvent อย่างไร

TriggerEvent ใช้ใน Context เดียวกัน ส่วน TriggerServerEvent ใช้ Client → Server.

source ใน Server Event คืออะไร

คือ Player ที่ Trigger Network Event จาก Client ตามบริบทของ Server Handler.

TriggerClientEvent ส่งให้ทุกคนอย่างไร

ใช้ Player Target เป็น -1 ใน Lua.

ต้องเชื่อข้อมูลที่ Client ส่งหรือไม่

ไม่ควร Cfx.re แนะนำให้ Validate Client Input และใช้ Server-side Data สำหรับข้อมูลสำคัญ.

ข้อมูลขนาดใหญ่ใช้ Event แบบไหนดี

Cfx.re แนะนำ TriggerLatentServerEvent หรือ TriggerLatentClientEvent สำหรับข้อมูลหลาย KB หรือขนาดใหญ่ เพื่อลดการ Block Network Channel.

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

FiveM Network Events ควรเริ่มจากการจำทิศทางให้ถูกก่อน:

TriggerEvent
= ภายใน Context เดียวกัน

TriggerServerEvent
= Client → Server

TriggerClientEvent
= Server → Client

ส่วน Event ที่ต้องเดินทางข้าม Client/Server ต้อง Register สำหรับ Network Usage ด้วย RegisterNetEvent.

สำหรับข้อมูลจำนวนมากควรพิจารณา Latent Events เพราะ Cfx.re ระบุว่า Standard Events ที่ส่ง Payload ใหญ่สามารถ Block Network Channel และอาจทำให้ Client Timeout ได้.

จุดสำคัญที่สุดคือ Client ควรเป็นผู้ขอ Action แต่ Server ควรเป็นผู้ตัดสิน Action สำคัญ เช่น Money, Inventory, Permission และ Gameplay State โดย Cfx.re แนะนำให้ตรวจข้อมูลเหล่านี้ฝั่ง Server ไม่ใช่เชื่อ Client Input โดยตรง.

สำหรับผู้อ่าน comsiam ให้จำสูตร “Client ขอ → Server ตรวจ → Server ทำ → Client แสดงผล” และ comsiam แนะนำให้ Network Event ทุกตัวส่งเฉพาะข้อมูลที่จำเป็น ตรวจ source และ Validate ข้อมูลฝั่ง Server ก่อนเปลี่ยน State สำคัญ จะช่วยให้ Resource มีโครงสร้างที่ดูแลง่ายและปลอดภัยกว่าการย้าย Logic สำคัญไปไว้ฝั่ง Client

Comments

Popular posts from this blog

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

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

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