VINDICTA
Hooking · Function
Bunni.fun
ChocoSploit
Cryptic
Potassium
Seliware
SirHurt
Solara
Velocity
Volcano
Volt
Wave
Xeno

hookmetamethod

Hooks a specific metamethod on an object's metatable.

function hookmetamethod(object: table, method: string, hook: function): function

Synopsis

How it works

Resolves the metatableMetatableA table attached to another table (or userdata) that defines operator overloading via metamethods (__index, __newindex, __call, etc.). Roblox Instances use shared read-only metatables for method dispatch. of object (bypassing __metatable guards like getrawmetatable), looks up the specified metamethodMetamethodA function in a metatable that overrides default behavior for operations like indexing (__index), assignment (__newindex), calling (__call), comparison (__eq), and arithmetic (__add, __mul, etc.)., and applies hookfunction to it. Returns a trampolineTrampolineA wrapper function that bounces (redirects) calls to another function. In executor context, newcclosure creates a C closure trampoline that calls the Luau function stored in its first upvalue. to the original metamethod. Because Roblox Instances share a single global metatable, hooking on any InstanceInstanceThe base class for all Roblox objects (Parts, Models, Scripts, GUIs, etc.). Instances form a tree hierarchy (the DataModel). In Luau, they appear as userdata with shared metatables. affects all Instances.

VM internals — NAMECALL dispatch

When Luau compiles colon-call syntax obj:Method(args), it emits two instructions:
NAMECALL  R(A), R(B), K(C)   -- look up method name K(C) on R(B)
CALL      R(A), nargs, nrets  -- call the resolved function
NAMECALL is a 32-bit instruction: bits [0:7] = opcode, [8:15] = A register, [16:23] = B register, [24:31] = aux (constant index stored in nextnext()Table traversal primitive. next(t, key) returns the next key-value pair after key, or nil when done. next(t, nil) returns the first pair. The underlying function used by pairs(). Traversal order is not guaranteed. word). The VM first tries a fast-path lookup on the object's metatableMetatableA table attached to another table (or userdata) that defines operator overloading via metamethods (__index, __newindex, __call, etc.). Roblox Instances use shared read-only metatables for method dispatch. __index. If the object is a userdataUserdataA Luau type for C-allocated memory blocks. Roblox Instances, Vector3s, CFrames, and other engine types are userdata with metatables providing their API. Cannot be created from Luau directly. with __namecall, the VM calls that metamethodMetamethodA function in a metatable that overrides default behavior for operations like indexing (__index), assignment (__newindex), calling (__call), comparison (__eq), and arithmetic (__add, __mul, etc.). directly and sets an internal namecall register to the method name string. Inside the hook, getnamecallmethod() reads this register.

Shared metatable implication

All Roblox Instances (Part, Model, RemoteEvent, etc.) share a single metatableMetatableA table attached to another table (or userdata) that defines operator overloading via metamethods (__index, __newindex, __call, etc.). Roblox Instances use shared read-only metatables for method dispatch. at the C++ level. Hooking __namecall on game intercepts every :Method() call on every InstanceInstanceThe base class for all Roblox objects (Parts, Models, Scripts, GUIs, etc.). Instances form a tree hierarchy (the DataModel). In Luau, they appear as userdata with shared metatables. in the game. This is why a single hook can intercept :FireServer(), :FindFirstChild(), :GetService(), etc.

Common hooks

  • __namecall — intercept all method calls (:FireServer, :FindFirstChild, etc.)
  • __index — intercept property reads (obj.Property). Dispatched by GETTABLEKS opcode
  • __newindex — intercept property writes (obj.Property = value). Dispatched by SETTABLEKS opcode
  • __tostring — control string representation (called by tostring())

Usage

Intercept __namecall on game
local origNamecall
origNamecall = hookmetamethod(game, "__namecall", function(self, ...)
  local method = getnamecallmethod()
  if method == "FireServer" then
    print("RemoteEvent fired:", ...)
  end
  return origNamecall(self, ...)
end)

Parameters

object table | userdata
The object whose metatable contains the metamethod to hook.
method string
The metamethod name, e.g. "__namecall", "__index", "__newindex".
hook function
The replacement function.

Returns

function A trampoline to the original metamethod implementation.
Recursive Loop Risk
Inside __namecall hooks, always use the trampoline with dot syntax (original(self, ...)) to avoid an infinite recursion loop. Using colon syntax will re-invoke the hook.