NewProxy is a built-in CET feature you can use to declare callback functions. You can use it to bind a Lua function as a callback with game's script system.
You can now generate NewProxy using NativeDB. You need to configure option Clipboard syntax to Lua. You can click on the "copy" button of a function, pick Copy NewProxy and it will copy the code in your clipboard. It only works for classes with their names ending with Listener.
CallbackName is an arbitrary name you define. A callback name can be formatted as follow On[Action] (e.g. OnDamaged or also OnPlayerDamaged).
CallbackDefinition is the signature of the script function (args) and the Lua function (callback) you want to be executed when the callback is triggered.
The list of arguments must indicate the name of the types to expect. For example with a callback function which receives a String, an Int32 and a reference to a GameObject, it should be defined like this:
args = {"String", "Int32", "handle:GameObject"}
In this case, you can define your function callback like this:
The signature of the function depends on the game's script function you want to register a callback for.
You can use NativeDB to know the types of arguments to declare. By default, the syntax will be written in Redscript. You can change the option Code syntax in the settings and select Pseudocode ยท Legacy instead. Basically, it will show you handle:GameObject instead of ref<GameObject> (among other things).
Use a proxy
Lets create a proxy:
listener =NewProxy({ OnHit = { args = {"handle:GameObject", "Uint32"},callback=function(shooter,damage)print("Hit by " ..NameToString(shooter:GetClassName()) .."!")print("You lost " ..tostring(damage) .." HP.")end }})
After creating the proxy, you can use it to pass the target and function you want to callback. Lets say a game's script is defined as:
We can call the function RegisterHit to register our callback with our proxy like this:
local awesome = AwesomePlayer.new() -- for example onlyawesome:RegisterHit(listener:Target(), listener:Function("OnHit"))
Note that the value, when calling listener:Function("OnHit"), is the same we declared in the proxy.
This way, you can create multiple callback in a proxy and you just need to call listener:Function with the name of the callback you want to use. For example:
This example will be using Codeware and its system to listen for game events. It will listen for the event Session/Ready and print a message in CET logs.
local mod = { listener =nil}-- Define our function to callbackfunctionOnReady(event)local isMenu = event:IsPreGame()print("Event \"Session/Ready\" triggered!")if isMenu thenprint("Player is in the pre-game menu")elseprint("Player is in the game")endendregisterForEvent('onInit', function()-- Create our proxy mod.listener =NewProxy({ OnSessionReady = {-- Type is defined in the wiki of Codeware args = {"handle:GameSessionEvent"},callback=function(event) OnReady(event) end } })-- Register our callback to listen for event "Session/Ready".local callbackSystem = Game.GetCallbackSystem()local target = mod.listener:Target()local fn = mod.listener:Function("OnSessionReady") callbackSystem:RegisterCallback("Session/Ready", target, fn)end)registerForEvent('onShutdown', function()-- Unregister our callback before our mod is "removed".local target = mod.listener:Target()local fn = mod.listener:Function("OnSessionReady") callbackSystem:UnregisterCallback("Session/Ready", target, fn)end)