Page cover

👾Metatable Functions

ดึง metatable ของค่าโดยไม่คำนึงถึงฟิลด์ __metatable ของ Value นั้นๆ

<table> getrawmetatable(<table> value)

ตัวอย่าง #1

-- ทำซ้ำโค้ดที่อยู่ภายในบล็อก while ในระหว่างรอ 1 วินาทีทุกครั้ง
while wait(1) do
    -- แสดงค่าของตัวแปร workspace.Camera ในคอนโซล (Console)
    print(workspace.Camera)
end

ตัวอย่าง #2

-- นำค่า metatable ของตัวแปร game มาเก็บในตัวแปร game_meta
local game_meta = getrawmetatable(game)

-- นำค่า __index ของ metatable มาเก็บในตัวแปร game_index
local game_index = game_meta.__index

-- ทำให้ metatable ของตัวแปร game เปลี่ยนแปลงค่าได้ (mutable) โดยใช้ setreadonly() โดยกำหนดให้เป็น false
setreadonly(game_meta, false) -- Required to avoid errors

-- กำหนดให้ตัวแปร game_meta เปลี่ยนแปลงค่าของ __index ใหม่โดยใช้ฟังก์ชัน (function) ที่กำหนดเอง
game_meta.__index = function(Instance, string)
    -- เมื่อมีการเรียกใช้ __index ของตัวแปร game_meta ด้วยตัวอักษร string

    -- ถ้า string คือ "Camera" ให้คืนค่าการเรียกใช้ __index ของ game โดยใช้ชื่อ Instance ของตัวแปร "Workspace"
    if string == "Camera" then
        return game_index(game, "Workspace")
    end

    -- หากไม่ใช่กรณีข้างต้น ให้คืนค่าการเรียกใช้ __index ของตัวแปร Instance ด้วยตัวอักษร string
    return game_index(Instance, string)
end

กำหนดตารางเมตาเทเบิลตัวแรกให้เป็นตารางที่ระบุ (provided mt) โดยไม่สนใจว่ามีฟิลด์ __metatable อยู่ในตารางเมตาเทเบิลตัวแรกหรือไม่" ซึ่งเป็นคำอธิบายของการใช้งานภาษาโปรแกรม Lua ในสภาวะที่ต้องการกำหนดตารางเมตาเทเบิลของค่าให้เป็นตารางที่กำหนดไว้ โดยไม่สนใจว่าตารางเมตาเทเบิลตัวแรกมีฟิลด์ __metatable อยู่หรือไม่

Hook Metamethod

เชื่อมต่อ Metamethod ที่ระบุไว้ในตารางเมตาเทเบิลของ Object กับฟังก์ชัน f

<function> hookmetamethod(<Instance> Object, <string> Metamethod, <function> f)

ตัวอย่าง

-- ข้อควรทราบ: โค้ดด้านล่างนี้ไม่ควรนำไปใช้ในโปรเจคจริง เพราะอาจก่อให้เกิดปัญหาในการทำงานของเกม

-- ควรให้คำเตือนว่าโค้ดนี้เป็นเพียงตัวอย่างการใช้งานและไม่ควรนำไปใช้ในโปรเจคจริง

-- __namecall Hook
local OldNamecall
OldNamecall = hookmetamethod(game, "__namecall", function(self, ...)
    -- ก่อนจะทำอะไรกับ Metatable "__namecall" ก่อนหน้านี้
    -- คืนค่า Metatable "__namecall" ตัวเก่า (OldNamecall) และคืนค่าตามการเรียกใช้งาน (self, ...)
    return OldNamecall(self, ...)
end)

-- __index Hook
local OldIndex
OldIndex = hookmetamethod(game, "__index", function(self, i)
    -- ก่อนจะทำอะไรกับ Metatable "__index" ก่อนหน้านี้
    -- คืนค่า Metatable "__index" ตัวเก่า (OldIndex) และคืนค่าตามการเรียกใช้งาน (self, i)
    return OldIndex(self, i)
end)

-- __newindex Hook
local OldNewIndex
OldNewIndex = hookmetamethod(game, "__newindex", function(self, i, v)
    -- ก่อนจะทำอะไรกับเมทาเทเบิล "__newindex" ก่อนหน้านี้
    -- คืนค่า Metatable "__newindex" ตัวเก่า (OldNewIndex) และคืนค่าตามการเรียกใช้งาน (self, i, v)
    return OldNewIndex(self, i, v)
end)

ตัวอย่าง : Basic Remote Spy

-- คำเตือน : โค้ดด้านล่างนี้ไม่ควรนำไปใช้ในโปรเจคจริง

-- ควรให้คำเตือนว่าโค้ดนี้เป็นเพียงตัวอย่างการใช้งานและไม่ควรนำไปใช้ในโปรเจคจริง

-- namecalls คือฟังก์ชันที่ถูกเรียกใช้งานด้วย : (ตัวอย่างเช่น RemoteEvent:FireServer())
local old -- กำหนดตัวแปร old เพื่อเก็บชื่อเมทาเมธอดเดิม (ชื่อเก่า) เนื่องจากจะทำการ hook เพื่อตรวจสอบ (เพื่อป้องกันการเกิดข้อผิดพลาดในการเรียกใช้งานที่ถูกต้อง)
old = hookmetamethod(game, "__namecall", function(self, ...)
    -- self = อินสแตนซ์ของ Remote
    -- ... = อาร์กิวเมนต์ของเมทอด
    local args = {...}
    if getnamecallmethod() == "FireServer" then -- ตรวจสอบว่าเมทาเมธอดที่ถูกเรียกใช้เป็น "FireServer"
        local Path = self:GetFullName() -- ดึงชื่อเส้นทางของ Remote
        local Arguments = table.concat(args, "\n") -- รวม Argument เป็นสตริง
        print(string.format("Path: %s\nArguments:\n%s", Path, Arguments)) -- แสดงข้อมูลที่ตรวจสอบผ่านทางคอนโซล (Console) ซึ่งเป็นตัวอย่างเพียงอย่างง่าย
        -- การใช้งาน remote spies ที่แสดงผลในคอนโซลนั้นไม่ควรเป็นวิธีการที่ดี นี่เป็นเพียงตัวอย่างการใช้งาน
    end
    return old(self, ...) -- ส่งคืนการเรียกใช้งานเมธอดเดิม (ชื่อเก่า)
end)

Last updated