👾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