FiveM RegisterNetEvent คืออะไร? วิธีรับ Network Event จาก Client และ Server

 FiveM RegisterNetEvent() คือ Function สำหรับ Register Event ให้สามารถถูกเรียกผ่าน Network ได้ เช่น Client ส่ง Event ไป Server หรือ Server ส่ง Event ไป Client

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

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

        print(
            src,
            itemName,
            amount
        )
    end
)

แล้ว Client สามารถส่ง Event มาได้ด้วย

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

Flow คือ

Client
↓
TriggerServerEvent
↓
Network
↓
Server
↓
RegisterNetEvent
↓
Event Handler

สิ่งสำคัญมากคือคำว่า Register Event ให้ใช้ผ่าน Network ไม่ได้หมายความว่า Event นั้นปลอดภัยจากการโกงโดยอัตโนมัติ

ถ้า Server เปิด Network Event ให้ Client เรียก Server ยังต้องตรวจข้อมูลที่ Client ส่งเข้ามาเองเสมอ

① RegisterNetEvent FiveM คืออะไร

RegisterNetEvent() มีหน้าที่ทำให้ Event สามารถถูก Trigger ข้าม Network Context ได้

ตัวอย่าง

Client → Server

หรือ

Server → Client

ใน Lua สามารถเขียน

RegisterNetEvent(
    'example:hello',
    function()
        print('Event received')
    end
)

เมื่อ Event ถูก Trigger Handler ที่กำหนดไว้จะทำงาน

② Syntax ของ RegisterNetEvent

รูปแบบปัจจุบันคือ

RegisterNetEvent(
    eventName,
    callback
)

ตัวอย่าง

RegisterNetEvent(
    'garage:open',
    function()
        print('Opening garage')
    end
)

eventName คือชื่อ Event

ส่วน callback คือ Function ที่ทำงานเมื่อ Event ถูกเรียก

③ Callback จำเป็นต้องใส่หรือไม่

ไม่จำเป็น

สามารถเขียนแบบแยกได้

RegisterNetEvent(
    'garage:open'
)

AddEventHandler(
    'garage:open',
    function()
        print('Opening garage')
    end
)

หรือเขียนแบบย่อ

RegisterNetEvent(
    'garage:open',
    function()
        print('Opening garage')
    end
)

ทั้งสองรูปแบบใช้ได้

④ แบบไหนควรใช้

สำหรับ Event ที่มี Handler เดียวและ Code ไม่ซับซ้อน แบบนี้อ่านง่าย

RegisterNetEvent(
    'shop:open',
    function()
        -- logic
    end
)

ถ้าต้องการแยก Registration กับ Handler หรือมี Architecture เฉพาะ อาจใช้

RegisterNetEvent(
    'shop:open'
)

AddEventHandler(
    'shop:open',
    function()
        -- logic
    end
)

เลือกตามความอ่านง่ายของ Resource

⑤ RegisterNetEvent ใช้ฝั่ง Server ได้ไหม

ได้ และเป็นหนึ่งใน Use Case ที่ใช้บ่อยที่สุด

เช่น Client ต้องการซื้อสินค้า

Client

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

Server

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

        -- validation
    end
)

นี่คือ Pattern

Client
→
Server

⑥ RegisterNetEvent ใช้ฝั่ง Client ได้ไหม

ได้

เช่น Server ต้องการส่ง Notification ไปยัง Player

Server

TriggerClientEvent(
    'notify:show',
    source,
    'ซื้อสินค้าสำเร็จ'
)

Client

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

นี่คือ Pattern

Server
→
Client

⑦ RegisterNetEvent ใช้ได้ทั้งสองฝั่ง

จำง่าย ๆ ว่า

SERVER

RegisterNetEvent
← TriggerServerEvent

และ

CLIENT

RegisterNetEvent
← TriggerClientEvent

ดังนั้น RegisterNetEvent() ไม่ได้เป็น Function เฉพาะ Server

ใช้ได้ทั้ง Client และ Server Lua Runtime

⑧ RegisterNetEvent ต่างจาก AddEventHandler อย่างไร

นี่เป็นจุดสำคัญที่สุดของหัวข้อนี้

AddEventHandler() ใช้ฟัง Event

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

แต่ไม่ได้หมายความว่า Event นั้นต้องเปิดสำหรับ Network

ส่วน

RegisterNetEvent()

ใช้ทำให้ Event สามารถใช้ผ่าน Network ได้

หลักง่าย ๆ คือ

AddEventHandler
→ Event Handler

RegisterNetEvent
→ Network-capable Event

⑨ Event ภายใน Server ควรใช้ RegisterNetEvent ไหม

ถ้า Event ต้องใช้เฉพาะ

Server
→
Server

และ Client ไม่จำเป็นต้องเรียก ควรพิจารณาใช้

AddEventHandler()

อย่างเดียว

ตัวอย่าง

AddEventHandler(
    'garage:vehicleStored',
    function(plate)
        print(plate)
    end
)

แล้ว Server Trigger

TriggerEvent(
    'garage:vehicleStored',
    plate
)

ไม่จำเป็นต้องเปิด Network โดยไม่มีเหตุผล

⑩ Event ภายใน Client ใช้อะไร

ถ้าต้องการ

Client
→
Client

สามารถใช้

AddEventHandler(
    'menu:open',
    function()
    end
)

แล้ว

TriggerEvent(
    'menu:open'
)

ไม่จำเป็นต้อง RegisterNetEvent() หากไม่มี Server ต้อง Trigger Event นี้

⑪ ทำไมไม่ควร RegisterNetEvent ทุก Event

เพราะ Network Event เพิ่มช่องทางที่อีก Context สามารถเรียก Event ได้

ตัวอย่าง Server Event

giveReward

ถ้ามันเป็น Server-internal Logic ไม่ควรเปิดให้ Client เรียกโดยไม่มีเหตุผล

หลักคือ

ต้องข้าม Network
→ RegisterNetEvent

ไม่ต้องข้าม Network
→ AddEventHandler

ช่วยลด Attack Surface ของ Resource

⑫ RegisterNetEvent ทำให้ Event ปลอดภัยไหม

ไม่

เอกสาร Cfx.re ใช้คำว่า Event ถูกทำให้พร้อมหรือ safe สำหรับ network use แต่คำนี้ไม่ได้หมายถึง Security Validation

เมื่อ Event เปิด Network แล้ว Client ที่ไม่ปลอดภัยอาจพยายาม Trigger Event นั้นได้

ดังนั้น

RegisterNetEvent
≠
Anti-Cheat

และ

RegisterNetEvent
≠
Server Validation

Developer ต้องเขียน Security Logic เอง

⑬ ตัวอย่าง RegisterNetEvent ที่ไม่ปลอดภัย

Server

RegisterNetEvent(
    'money:add',
    function(amount)
        AddMoney(
            source,
            amount
        )
    end
)

Client อาจพยายาม Trigger

TriggerServerEvent(
    'money:add',
    1000000
)

ปัญหาไม่ได้อยู่ที่ RegisterNetEvent()

ปัญหาอยู่ที่ Server เชื่อ amount จาก Client

⑭ Event ที่ปลอดภัยกว่าควรออกแบบอย่างไร

Client ส่งเพียง Request

TriggerServerEvent(
    'delivery:complete'
)

Server

RegisterNetEvent(
    'delivery:complete',
    function()
        local src = source

        -- ตรวจ active job
        -- ตรวจ position
        -- ตรวจ state
        -- ตรวจ cooldown

        local reward = 500

        AddMoney(
            src,
            reward
        )
    end
)

Server คำนวณ Reward เอง

⑮ source ใน RegisterNetEvent คืออะไร

เมื่อ Event ถูก Trigger จาก Client ไป Server ใน Handler ฝั่ง Serverสามารถใช้

source

เพื่อระบุ Player Source ของผู้ที่ส่ง Event

ตัวอย่าง

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

        print(
            'Event from:',
            src
        )
    end
)

จึงไม่จำเป็นต้องให้ Client ส่ง Server ID ของตัวเองมาเป็น Authority

⑯ ควรเก็บ source เป็น local หรือไม่

ควรใน Handler ที่ต้องใช้หลายจุด

local src = source

จากนั้นใช้

GetPlayerName(src)

หรือ Framework Player Lookup ตามระบบ

ช่วยให้ Code อ่านง่ายขึ้นและลดความสับสนใน Async Logic

⑰ RegisterNetEvent รับ Parameter ได้ไหม

ได้

Client

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

Server

RegisterNetEvent(
    'shop:buy',
    function(itemName, amount)
        print(
            itemName,
            amount
        )
    end
)

Parameter จะถูกส่งไปยัง Callback ตามลำดับ

⑱ รับ String ได้ไหม

ได้

RegisterNetEvent(
    'example:name',
    function(name)
        print(name)
    end
)

Client

TriggerServerEvent(
    'example:name',
    'John'
)

แต่หากค่าใช้กับระบบสำคัญ Server ควรตรวจ Type และ Value ด้วย

⑲ รับ Number ได้ไหม

ได้

RegisterNetEvent(
    'shop:buy',
    function(amount)
        print(amount)
    end
)

แต่ไม่ควรคิดว่า Number ทุกค่าใช้ได้

Client อาจส่ง

-999
0
999999999

Server ต้องตรวจ Range

⑳ ตรวจ Type อย่างไร

ตัวอย่าง

RegisterNetEvent(
    'shop:buy',
    function(itemName, amount)

        if type(itemName) ~= 'string' then
            return
        end

        if type(amount) ~= 'number' then
            return
        end

        -- continue
    end
)

นี่เป็น Validation ขั้นพื้นฐาน

㉑ ตรวจ Range อย่างไร

หลังตรวจ Type แล้วควรตรวจ Value

if amount < 1 then
    return
end

if amount > 100 then
    return
end

ถ้าระบบอนุญาตซื้อสูงสุด 100 ชิ้น

Client ไม่ควรสามารถส่ง 1,000,000 แล้ว Server ทำตาม

㉒ ตรวจ Item อย่างไร

อย่าเชื่อชื่อ Item โดยตรง

ตัวอย่าง

local item =
    Config.Items[itemName]

if not item then
    return
end

Server ใช้ Allowlist หรือ Item Definition ของตัวเอง

จากนั้นค่อยทำ Business Logic

㉓ ตรวจราคาอย่างไร

Client สามารถส่งชื่อ Item

water

แต่ Server ควรดึงราคาจาก Data ที่เชื่อถือได้

local price =
    Config.Items[itemName].price

ไม่ควรให้ Client ส่ง

price = 1

แล้ว Server เชื่อ

㉔ ตรวจ Money ที่ไหน

Server ควรอ่านยอดเงินจาก

  • Framework Player Data

  • Economy System

  • Server Cache

  • Database/State ที่เชื่อถือได้

ตาม Architecture

ตัวอย่าง Flow

Client:
ขอซื้อ water

Server:
หาราคา
↓
อ่านยอดเงิน
↓
ตรวจยอดเงิน
↓
ทำ Transaction

㉕ ตรวจ Inventory ที่ไหน

Server

เพราะ Client Inventory State อาจถูกแก้หรือปลอมได้

Server ควรตรวจ

Item มีจริง?
มีจำนวนเท่าไร?
น้ำหนักพอไหม?
เพิ่ม/ลบได้ไหม?

ก่อนทำ Action

㉖ ตรวจ Permission อย่างไร

Event ที่เป็น Admin Action ต้องตรวจ Permission Server-side

ตัวอย่าง

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

        if not IsServerAdmin(src) then
            return
        end

        -- action
    end
)

อย่าให้ Client ส่ง

isAdmin = true

แล้วถือว่าเป็นหลักฐาน

㉗ ตรวจ Position ทำไม

สมมติ Event

job:complete

Client อาจ Trigger จากที่ไหนก็ได้หาก Serverไม่ตรวจ

Server ควรตรวจว่า Player อยู่ใกล้จุดที่กำหนดจริงตามระบบที่รองรับ

Flow ที่ดีกว่า

RegisterNetEvent
↓
Get Player
↓
Check Position
↓
Check Active Job
↓
Reward

㉘ ตรวจ State ทำไม

บาง Action ต้องมี State ก่อนหน้า

ตัวอย่าง

job:start
↓
ทำงาน
↓
job:complete

Server ควรเก็บว่า Player เริ่มงานจริง

เช่น

local activeJobs = {}

แล้วตอน Complete

local job =
    activeJobs[source]

if not job then
    return
end

Client จึงไม่สามารถข้ามขั้นตอนง่าย ๆ เพียง Trigger Event สุดท้าย

㉙ Cooldown สำคัญอย่างไร

Network Event สามารถถูกเรียกถี่ได้

Event สำคัญจึงควรพิจารณา

Cooldown
Rate Limit

โดยเฉพาะ

  • Reward

  • Database Query

  • Vehicle Spawn

  • Admin Action

  • External API

Server ต้องป้องกัน Event Spam ตามความเหมาะสม

㉚ RegisterNetEvent กับ Rate Limit

ตัวอย่าง Concept

RegisterNetEvent
↓
รับ Event
↓
Rate Limit Check
↓
Validation
↓
Business Logic

แม้ Parameter ถูกทั้งหมด แต่ถ้า Player เรียก Event 500 ครั้งต่อวินาที ก็ยังเป็นปัญหาได้

㉛ RegisterNetEvent กับ TriggerServerEvent

เป็นคู่สำคัญสำหรับ

Client → Server

Client

TriggerServerEvent(
    'garage:store',
    networkId
)

Server

RegisterNetEvent(
    'garage:store',
    function(networkId)
        local src = source

        -- validation
    end
)

จำเป็นต้องเข้าใจทั้งสอง Function ร่วมกัน

㉜ RegisterNetEvent กับ TriggerClientEvent

เป็นคู่สำหรับ

Server → Client

Server

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

Client

RegisterNetEvent(
    'garage:open',
    function(vehicles)
        -- open UI
    end
)

㉝ RegisterNetEvent กับ TriggerEvent

TriggerEvent() ทำงานภายใน Context เดียวกัน

แต่ RegisterNetEvent() ทำให้ Event สามารถใช้ข้าม Context ได้

อย่างไรก็ตาม Event ที่ Register ด้วย RegisterNetEvent() ยังสามารถถูกเรียกใน Context เดียวกันได้ด้วย

ดังนั้นอย่าคิดว่า Net Event รับได้เฉพาะ Network เท่านั้น

㉞ RegisterNetEvent ไม่บล็อก Local Trigger

นี่เป็นรายละเอียดสำคัญ

ถ้ามี

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

การ Register แบบ Network ไม่ได้หมายความว่า Event จะถูกบังคับให้มาจากอีกฝั่งเพียงอย่างเดียว

จึงต้องแยก Security Requirement ให้ชัด

โดยเฉพาะ Client Event ที่ต้องการรับเฉพาะจาก Server

㉟ Client Event รับเฉพาะ Server ได้ไหม

หากต้องการเพิ่มการตรวจว่า Network Event บน Client ถูกส่งมาจาก Server จริง Cfx.re ระบุ Pattern ที่ใช้ตรวจ

RegisterNetEvent(
    'example:test',
    function()
        if source ~= 65535 then
            return
        end

        -- event from server
    end
)

ใน Client Network Event ที่มาจาก Server จะใช้ Net Source ID 65535

Pattern นี้ช่วยป้องกัน Local Client Resource Trigger Event เดียวกันในบางกรณี

แต่ Client-side Protection ไม่ใช่ Security Boundary ที่สมบูรณ์

ข้อมูลสำคัญยังต้องมี Server Authority

㊱ ต้องใช้ source ~= 65535 ทุก Client Event ไหม

ไม่จำเป็นทุก Event

ใช้เมื่อคุณต้องการ Event ที่ถูกออกแบบให้รับเฉพาะจาก Server และต้องการลดการ Trigger จาก Client Context เดียวกัน

สำหรับ Event ที่ไม่มีผล Security หรือ Local Trigger เป็นส่วนหนึ่งของ Design ก็ไม่จำเป็น

ต้องเลือกตาม Architecture

㊲ RegisterNetEvent กับ Client Security

แม้ใส่ Client-side Check แล้วก็ต้องจำว่า Client Environment อยู่บนเครื่องผู้เล่น

ดังนั้น Client Logic สามารถถูก Manipulate ได้

อย่าวาง

Money Authority
Permission Authority
Inventory Authority
Reward Authority

ไว้ Client เพียงเพราะ Event รับจาก Server

Server ยังต้องเป็น Source of Truth สำหรับข้อมูลสำคัญ

㊳ RegisterNetEvent กับ Database

Database Event ควรรับ Action ที่ชัดเจน

เช่น

RegisterNetEvent(
    'garage:store',
    function(networkId)
        -- validate
        -- database
    end
)

ไม่ควรสร้าง

RegisterNetEvent(
    'database:execute',
    function(sql)
        -- execute client SQL
    end
)

เด็ดขาด

Client ไม่ควรส่ง SQL มาให้ Server Execute

㊴ RegisterNetEvent กับ NUI

Flow ที่พบบ่อยคือ

NUI
↓
Client
↓
TriggerServerEvent
↓
Server RegisterNetEvent

ตัวอย่าง

RegisterNUICallback(
    'buyItem',
    function(data, cb)

        TriggerServerEvent(
            'shop:buy',
            data.item,
            data.amount
        )

        cb({})
    end
)

Server รับด้วย RegisterNetEvent()

แต่ NUI Data ยังเป็น Client Input

ต้อง Validate Server-side

㊵ RegisterNetEvent ใช้เปิด NUI ได้ไหม

ได้ใน Client

Server

TriggerClientEvent(
    'garage:openUi',
    source,
    vehicles
)

Client

RegisterNetEvent(
    'garage:openUi',
    function(vehicles)

        SetNuiFocus(
            true,
            true
        )

        SendNUIMessage({
            action = 'open',
            vehicles = vehicles
        })
    end
)

เป็น Pattern Server → Client → NUI

㊶ RegisterNetEvent กับ ESX

ESX Resource จำนวนมากใช้ Network Events

ตัวอย่าง Architecture

ESX Client
↓
TriggerServerEvent
↓
ESX Server
↓
RegisterNetEvent

หรือกลับกัน

ESX Server
↓
TriggerClientEvent
↓
Client RegisterNetEvent

แต่ Framework ไม่ทำให้ Event ปลอดภัยโดยอัตโนมัติ

Developer ยังต้อง Validate Input

㊷ RegisterNetEvent กับ QBCore

หลักเดียวกัน

QBCore Resource มีทั้ง

  • Framework Events

  • Custom Events

  • Callbacks

  • Exports

Network Event ที่ Client เรียก Server ยังต้องตรวจ Player State และ Permission ตามระบบ

㊸ RegisterNetEvent กับ Qbox

เหมือนกัน

FiveM Event Runtime อยู่ใต้ Framework อีกชั้นหนึ่ง

ดังนั้นการเข้าใจ

RegisterNetEvent
TriggerServerEvent
TriggerClientEvent
AddEventHandler

จะช่วยให้ Debug Qbox Resource ได้ง่ายขึ้น

㊹ RegisterNetEvent กับ JavaScript

ใน JavaScript Runtime จะใช้แนวคิด

onNet(
    'example:test',
    (data) => {
        console.log(data);
    }
);

แทน Lua RegisterNetEvent() แบบตรงตัว

แนวคิดเหมือนกันคือ Register Network Event Handler

㊺ JavaScript onNet รับ Local Event ได้ไหม

Cfx.re ระบุว่า onNet() สามารถถูก Execute ได้ทั้ง Local และ Remote Context เช่นเดียวกับหลักที่ต้องระวังใน Network Events

ดังนั้นอย่าคิดว่า Network Handler ถูกบังคับให้มาจากอีกฝั่งเสมอไป

Security ต้องออกแบบเพิ่มเติมตาม Use Case

㊻ C# ต้อง RegisterNetEvent แบบ Lua ไหม

Cfx.re ระบุว่า Lua และ JavaScript ต้อง Register Event สำหรับ Network Use

ส่วน C# ไม่ต้องทำ Manual Registration แบบเดียวกัน

C# ใช้ Event Handler System และ Attribute/API ของ Runtime เช่น

EventHandler

ตาม C# Scripting Model

ดังนั้น Concept เหมือนกัน แต่ Syntax และ Registration Model ต่างกัน

㊼ RegisterNetEvent กับ Event Contract

Project ใหญ่ควรระบุ Contract ของ Network Event

ตัวอย่าง

Event:
shop:buy

Direction:
Client → Server

Arguments:
itemName: string
amount: number

Validation:
item allowlist
amount range
player money
inventory
position
cooldown

ช่วยให้ Security Review และ Debug ง่ายขึ้นมาก

㊽ Event Name ควรตั้งแบบไหน

ควรมี Prefix ตาม Resource

เช่น

mygarage:storeVehicle
mygarage:requestVehicles
mygarage:takeOutVehicle

ดีกว่า

store
get
update

เพราะ Server หนึ่งอาจมี Custom Events จำนวนมาก

㊾ ชื่อ Event ซับซ้อนช่วย Security ไหม

ไม่

ตัวอย่าง

x8f_secret_money_12345

ไม่ได้ทำให้ Event ปลอดภัย

Client ที่ถูกดัดแปลงไม่ควรถูกป้องกันด้วยหลัก

หวังว่าจะหาชื่อ Event ไม่เจอ

Security ต้องมาจาก Validation และ Authority

㊿ RegisterNetEvent Trigger บ่อยมีผลไหม

มี

แม้ Register ตัว Handler ไม่ใช่ปัญหา แต่ Network Event ที่ถูก Trigger ถี่มากสามารถสร้าง

  • Network Traffic

  • Serialization Cost

  • Server CPU

  • Client CPU

  • Database Load

ได้

จึงควรหลีกเลี่ยง Network Event ทุก Frame หากไม่มีเหตุผล

51 Parameter ใหญ่เกินไปมีผลไหม

มี

Event Arguments ต้องถูก Serialize/Deserialize

จึงควรส่งข้อมูลให้เล็กและง่ายเท่าที่ทำได้

เช่น Client ต้องการแค่

money
job

ไม่จำเป็นต้องส่ง Player Data ทั้งก้อน

52 Event รับ Table ใหญ่ควรระวังอะไร

ต้องระวัง

  • Payload Size

  • Nested Data

  • Serialization

  • Network Bandwidth

  • Processing

สำหรับ Payload ใหญ่จริง FiveM มี Latent Event API

แต่ก่อนใช้ Latent Event ควรถามก่อนว่า Data ทั้งหมดจำเป็นหรือไม่

53 RegisterNetEvent ไม่ทำงานแก้อย่างไร

ตรวจ

① Resource Start หรือยัง
② Event Name ตรงไหม
③ RegisterNetEvent อยู่ถูกฝั่งไหม
④ TriggerServerEvent หรือ TriggerClientEvent ใช้ถูกทิศทางไหม
⑤ client.lua/server.lua ถูกโหลดหรือไม่
⑥ มี Error ก่อน Register หรือไม่
⑦ Parameter ถูกต้องไหม
⑧ F8 มี Error หรือไม่
⑨ Server Console มี Error หรือไม่

54 วิธี Debug RegisterNetEvent ฝั่ง Server

Client

print('sending event')

TriggerServerEvent(
    'training:test',
    'hello'
)

Server

RegisterNetEvent(
    'training:test',
    function(message)

        local src = source

        print(
            'event received',
            src,
            message
        )
    end
)

ถ้า Client Print ทำงานแต่ Serverไม่ Print ให้ตรวจ Network Event Registration และชื่อ Event

55 วิธี Debug RegisterNetEvent ฝั่ง Client

Server

print(
    'sending to',
    source
)

TriggerClientEvent(
    'training:message',
    source,
    'Hello'
)

Client

RegisterNetEvent(
    'training:message',
    function(message)

        print(
            'received:',
            message
        )
    end
)

ถ้า Server ส่งแล้ว Client ไม่ได้รับ ให้ดู F8 Console และ Target Player

56 AddEventHandler หลัง RegisterNetEvent ยังใช้ได้ไหม

ได้

ตัวอย่าง

RegisterNetEvent(
    'example:test'
)

local handler =
    AddEventHandler(
        'example:test',
        function()
            print('hello')
        end
    )

AddEventHandler() ยังคืน Handler Reference ที่สามารถใช้กับ

RemoveEventHandler()

ได้หาก Architecture ต้องการถอด Listener ภายหลัง

57 RemoveEventHandler คืออะไร

ใช้ลบ Event Handler ที่เคยเพิ่มผ่าน AddEventHandler()

ตัวอย่าง

local handler =
    AddEventHandler(
        'example:test',
        function()
            print('hello')
        end
    )

RemoveEventHandler(
    handler
)

มีประโยชน์สำหรับ Dynamic Listeners บางประเภท

แต่ Resource ทั่วไปไม่จำเป็นต้อง Remove Handler ทุกตัว

58 Checklist ก่อนใช้ RegisterNetEvent

ก่อน Register Network Event ใหม่ ให้ถามว่า

① Event ต้องข้าม Network จริงไหม?
② ถ้าไม่ต้อง ใช้ AddEventHandler แทนได้ไหม?
③ Direction คือ Client→Server หรือ Server→Client?
④ Parameter มีอะไร?
⑤ Type ถูกตรวจหรือยัง?
⑥ Range ถูกตรวจหรือยัง?
⑦ Server เชื่อ Client มากเกินไปหรือไม่?
⑧ Permission ตรวจ Server-side หรือยัง?
⑨ Money/Inventory ใช้ Server Data หรือยัง?
⑩ ต้องตรวจ Position/State หรือไม่?
⑪ ต้อง Rate Limit หรือไม่?
⑫ Event Trigger บ่อยเกินไปหรือไม่?

Checklist นี้ช่วยลดปัญหาที่พบบ่อยได้มาก

59 RegisterNetEvent ควรใช้เมื่อไร

ใช้เมื่อ Event จำเป็นต้องสื่อสารข้าม

Client ↔ Server

ตัวอย่าง

Client ซื้อสินค้า
→ Server

Server ส่ง Notification
→ Client

Client ขอ Garage Data
→ Server

Server Update HUD
→ Client

หากเป็น

Client → Client

หรือ

Server → Server

และไม่ต้อง Network ควรพิจารณา Local Event

60 หลักการจำ RegisterNetEvent แบบง่ายที่สุด

จำประโยคนี้

RegisterNetEvent
=
เปิด Event ให้ใช้ผ่าน Network

แต่ต้องตามด้วยอีกประโยคทันทีว่า

Network Event
=
ต้องคิดเรื่อง Security

และ

Client Input
=
ต้อง Validate

ถ้าจำสามประโยคนี้ได้ จะเข้าใจการใช้ RegisterNetEvent() ได้ถูกทางตั้งแต่เริ่มต้น

คำถามที่พบบ่อยเกี่ยวกับ FiveM RegisterNetEvent

RegisterNetEvent คืออะไร

คือ Function Lua สำหรับ Register Event ให้สามารถใช้ผ่าน Network ได้

RegisterNetEvent ใช้ Client ได้ไหม

ได้ Client ใช้รับ Event จาก Server ได้

RegisterNetEvent ใช้ Server ได้ไหม

ได้ Server ใช้รับ Event จาก Client ได้

Client ส่ง Event ไป Server ใช้อะไร

Client ใช้ TriggerServerEvent() และ Server รับด้วย RegisterNetEvent()

Server ส่ง Eventไป Client ใช้อะไร

Server ใช้ TriggerClientEvent() และ Client รับด้วย RegisterNetEvent()

RegisterNetEvent ต่างจาก AddEventHandler อย่างไร

AddEventHandler() ใช้ Listen Event ส่วน RegisterNetEvent() ทำให้ Event รองรับ Network Use

Event ภายใน Server ต้อง RegisterNetEvent ไหม

ไม่จำเป็นหาก Event เป็น Server → Server เท่านั้น ใช้ AddEventHandler() ได้

RegisterNetEvent ทำให้ Event ปลอดภัยไหม

ไม่ มันทำให้ Event ใช้ผ่าน Network ได้ แต่ Server ยังต้อง Validate Client Input เอง

RegisterNetEvent รับ Parameter ได้ไหม

ได้

source คืออะไร

ใน Server Network Event เป็น Player Source ของ Client ที่ Trigger Event เข้ามา

RegisterNetEvent รับ Table ได้ไหม

ได้กับ Data Type ที่ Runtime รองรับ แต่ควรส่งข้อมูลให้เล็กและจำเป็นเท่านั้น

C# ต้องใช้ RegisterNetEvent หรือไม่

C# ไม่ต้อง Register Network Event แบบ Manual เหมือน Lua/JavaScript ตาม Scripting Model ของ Cfx.re

JavaScript ใช้อะไรแทน RegisterNetEvent

ใช้ onNet() สำหรับ Network Events

สรุป FiveM RegisterNetEvent คืออะไร

FiveM RegisterNetEvent() คือ Function สำหรับทำให้ Event สามารถรับการ Trigger ผ่าน Network และสามารถกำหนด Callback ที่ทำงานเมื่อ Event ถูกเรียกได้

รูปแบบง่ายที่สุดคือ

RegisterNetEvent(
    'eventName',
    function(...)
        -- event logic
    end
)

สำหรับ Client → Server

Client
↓
TriggerServerEvent
↓
Server
↓
RegisterNetEvent

สำหรับ Server → Client

Server
↓
TriggerClientEvent
↓
Client
↓
RegisterNetEvent

แต่ถ้า Event อยู่ฝั่งเดียว เช่น

Server → Server

ควรใช้

AddEventHandler()

หากไม่มีเหตุผลต้องเปิด Network

และเรื่องสำคัญที่สุดคือ

RegisterNetEvent
ไม่ได้ทำให้ Client Input เชื่อถือได้

Server ต้องตรวจ Parameter, Money, Inventory, Position, Permission, State และเงื่อนไขอื่นที่เกี่ยวข้องด้วยข้อมูลฝั่ง Server

สำหรับคนที่เรียน FiveM Developer กับ comsiam หากเข้าใจ RegisterNetEvent() ให้ถูก จะเริ่มมอง Network Event ไม่ใช่แค่ Function สำหรับส่งข้อมูล แต่เป็น Trust Boundary ระหว่าง Client กับ Server ซึ่งต้องออกแบบทั้งด้าน Logic, Security และ Performance

เมื่อเข้าใจจุดนี้แล้ว หัวข้อถัดไปของ comsiam คือ AddEventHandler() ซึ่งจะอธิบายการสร้าง Event Listener, Local Events, Handler Reference และความแตกต่างกับ RegisterNetEvent() ให้ละเอียดขึ้น

Comments

Popular posts from this blog

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

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

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