Cannot call cb from server to client

Hi! I’m trying to help a friend out and I am stuck. So in my server, I have an event that takes the callback from my client and calls it, this is good for triggering functions that you can’t trigger on a specific side, however, all I get is “object is not a string”

client.lua

local QBCore = exports['qb-core']:GetCoreObject()
for i = 1, #Config.Objects do
    local model = Config.Objects[i]
    exports['qb-target']:AddTargetModel(model, { -- This defines the models, can be a string or a table
  options = { -- This is your options table, in this table all the options will be specified for the target to accept
    { -- This is the first table with options, you can make as many options inside the options table as you want
      num = 1, -- This is the position number of your option in the list of options in the qb-target context menu (OPTIONAL)
      type = "client", -- This specifies the type of event the target has to trigger on click, this can be "client", "server", "command" or "qbcommand", this is OPTIONAL and will only work if the event is also specified
      event = "Test:Event", -- This is the event it will trigger on click, this can be a client event, server event, command or qbcore registered command, NOTICE: Normal command can't have arguments passed through, QBCore registered ones can have arguments passed through
      icon = 'fas fa-example', -- This is the icon that will display next to this trigger option
      label = 'Test', -- This is the label of this option which you would be able to click on to trigger everything, this has to be a string
      action = function(entity) -- This is the action it has to perform, this REPLACES the event and this is OPTIONAL
        TriggerServerEvent("myDustbin:GetServerCallback", Test)
      end,
      canInteract = function(entity, distance, data) -- This will check if you can interact with it, this won't show up if it returns false, this is OPTIONAL
        if IsPedAPlayer(entity) then return false end -- This will return false if the entity interacted with is a player and otherwise returns true
        return true
      end,
    }
  },
  distance = 2.5, -- This is the distance for you to be at for the target to turn blue, this is in GTA units and has to be a float value
})
end

function Test(playerItems)
    print("e")
end

server.lua

local QBCore = exports['qb-core']:GetCoreObject()

RegisterServerEvent("myDustbin:GetServerCallback")
AddEventHandler("myDustbin:GetServerCallback", function (cb)
    cb("ok")
end)

Is the error on the client or the server?

Also which line is it reporting the line on?

Also, what kind of data are you expecting to get back on that particular line? (An example type (string, number, bool, etc) and an example of what you’re expecting back would help tremendously)

Please let me know and I’ll see if I can find the issue;

The error is server side. I’m trying to pass a function and call it server side from client side

Try this?

client.lia

local QBCore = exports['qb-core']:GetCoreObject()

-- Loop through the Config.Objects table to add each object to qb-target
for i = 1, #Config.Objects do
    local model = Config.Objects[i]
    exports['qb-target']:AddTargetModel(model, {
        options = {
            {
                num = 1,
                type = "client",
                event = "Test:Event", -- Assuming this event is handled somewhere in your client script
                icon = 'fas fa-example',
                label = 'Test',
                action = function(entity)
                    -- You should pass the entity to the server event if needed
                    TriggerServerEvent("myDustbin:GetServerCallback", entity)
                end,
                canInteract = function(entity, distance, data)
                    -- Assuming IsPedAPlayer is a valid function in your environment
                    if IsPedAPlayer(entity) then return false end
                    return true
                end,
            }
        },
        distance = 2.5,
    })
end

-- The Test function should be registered to an event if it's supposed to be triggered by an event
-- RegisterNetEvent("Test:Event")
-- AddEventHandler("Test:Event", function(entity)
--     Test(entity)
-- end)

-- If Test is not an event handler but a standalone function, you don't need the above code.
function Test(entity)
    -- entity is passed in, but not used. Assuming 'Test' functionality is correctly implemented.
    print("Test function called.")
end

server.lua

local QBCore = exports['qb-core']:GetCoreObject()

RegisterServerEvent("myDustbin:GetServerCallback")
AddEventHandler("myDustbin:GetServerCallback", function (entity)
    -- Perform checks or get data based on the entity if necessary
    local data = "ok" -- Assuming "ok" is the data you want to send back

    -- Trigger a client event as a callback with the data, make sure to send it back to the source player
    TriggerClientEvent("myDustbin:ServerCallback", source, data)
end)

Explain what you did so they understand why their code doesn’t work if yours does. IsPedAPlayer is a native function so it of course exists in the client environment as well. The Test function only needs to be registered as a network event if the server is trying to trigger it, and you have his server file triggering an event that doesn’t exist now, “myDustbin:ServerCallback”.

You can’t “cb” a function like that across server>client/client>server. You need to trigger network events and pass the data you are expecting. QBCore and ESX both have callback functionality implemented directly into them, and your files already collect the QBCore object, so just use the frameworks callback system since it already handles the event registration etc.
client

QBCore.Functions.TriggerCallback("myDustbin:GetServerCallback", Test)

server

QBCore.Functions.CreateCallback("myDustbin:GetServerCallback", function(source, cb)
    cb("ok")
end)

When using these in place of TriggerServerEvent and RegisterServerEvent... the client should print “e” to their console after the server triggers the cb(“ok”)

1 Like

Why does it do this and not my events?

I don’t understand your question. With the understanding I have taken from the question I will answer with:
The framework functionality for server to client, and in the case of QBCore client to server, function callbacks has internal code that creates the proper network events and triggers them accordingly when calling these callback functions.
The server creates a server side function to handle the callbacks storage
image
The client triggers a network event to tell the server to start the callback
image
The server internally handles the callback function, then triggers a network event to pass the data to the client
image
image
Then the client handles the triggered network event, and runs the callback function provided on its side
image

Your code never handles the network events and instead just attempts to run the function passed to the server, which as far as I understand, you can not pass functions across server>client/client>server because they get converted into a function reference, which is stored independently in each environment. So you are passing a reference to the server for Test, not actually passing the function, and the server does not have the reference to Test, so it can not find it.

1 Like