Function Refs

Is there a way to invoke function refs passed to the server?
I tried something like this but ‘Nope’

Citizen.CreateThread(function ()
	local function IsFunctionRef (cb)
		return type(cb) == 'table' and rawget(cb, '__cfx_functionReference')
	end
         -- Server
	if IsDuplicityVersion() then
		RegisterServerEvent('some_event_func')
		AddEventHandler('some_event_func', function (str, cb)
			-- Nope ?
			TriggerClientEvent(rawget(cb, '__cfx_functionReference'), source, 'RECEIVED_CALLBACK')

			-- Nope ?
			cb('SOME_DATA_BACK')
		end)
	else
        -- Client
		local handler = function (str) 
                        RemoveEventHandler(handle)
			print('HERE');
		end

		local token = Citizen.GetFunctionReference(handler)
		local handle = AddEventHandler(Citizen.GetFunctionReference(handler))

		TriggerServerEvent('some_event_func', 'SOME_DATA', handler)
	end
end)

EDIT: If i pass the ref handle back through a seperate handler, will it be able to invoke the fn’s no matter the containing resource or?

Thnx

… what?! You shouldn’t do anything with internal fields, also you can invoke things directly just fine without having to handle the internal data, at least if that backend code still works:

-- client
TriggerServerEvent('myEvent', function(wew)
    print('the server wants you to know ' .. wew)
    return 42
end)

-- server
RegisterNetEvent('myEvent')

AddEventHandler('myEvent', function(cb)
    local val = cb('this might work')

    -- this will internally schedule a Citizen.Await, probably
    print('the client told us about ' .. tostring(val))
end)

the same will work in C# I believe:

EventHandlers["myEvent"] += new Action<dynamic>(async cb =>
{
    dynamic val = await cb("oh!");

    Debug.WriteLine($"client said {val}");
});

(note that both snippets of code were untested, but it should be easy to see the concept)


if IsDuplicityVersion () then
    RegisterNetEvent('playerSpooned')
    AddEventHandler('playerSpooned', function (fn)
        TriggerClientEvent('ReceiveCallback', source, fn, msgpack.pack({ 'Welcome to the server.' }))
    end)
else

    function ClientFunction (msg)
        print('RECEIVED MESSAGE: ' .. (msg or ''))
    end

    RegisterNetEvent('ReceiveCallback')    
    AddEventHandler('ReceiveCallback', function (callback, payload)
        print('Invoking callback sent from server.')
        
        if type(callback) == 'table' then
            payload = payload or msgpack.pack({})
            InvokeFunctionReference(callback.__cfx_functionReference, payload, payload:len(), 0)
        else
            print("Callback was not a function")
        end
    end)


    local hasSpawned = false

    AddEventHandler('playerSpawned', function () 
        if not hasSpawned then
            hasSpawned = true
            TriggerServerEvent('playerSpooned', ClientFunction)
        end
    end)
end