Citizen.SetEventRoutine methods can be used?

Hello everyone,

I was diving deep into the subject of events, not to use them as the default, but to make an alternate implementation.

During my research, I discovered that a method called SetEventRoutine exists in the Citizen object and is used by default in server files that build the environment for resources. (fivem/scheduler.lua at 29fc26752ab72805f53a2c489fc46094ca1f8714 · citizenfx/fivem · GitHub link will highlight the specified function and his content)

Since all the methods are not necessarily present in the environment of the resource. I checked if the founded function exist into resources environnement, and if it could be called, and I tried to use it

--- @param eventName string name of the received event
--- @param payload string stringified and message packed payload
--- @param netId string stringified network client identifier 
local function EventDispatchRoutine(eventName, payload, netId)
    print(("^1Event '^3%s^1' received from netId '^3%s^1'^7"):format(eventName, netId))
    -- Custom event dispatch here
end
  
Citizen.SetEventRoutine(EventDispatchRoutine)

It’s seem’s the function exist, can be called, but … it seem that the call to this method is not taken into account.

And then, i was wondering… is it a method wich could be called only once ? or not ? So i remove the call to the function made by default in Cfx code when creating resource env, and test again the same code without any modification in my resource. And surprisingly… it works and my custom event dispatch function was called !

So… I’m wondering… is this a desired mechanic by Cfx? or a bug? And, If it is a desired mechanic , Is it possible to make it evolve ? and to allow the call of SetEventRoutine for overloading with our own events managing process ? or the integration of a way to register middleware function to allow a pre-processing of events ?

Thanks in advance for anyone who will respond
Have a great day

2 Likes

In part, this seems like an instance of the XY problem, and you could be better helped by explaining what you want to do, rather than wondering why the attempted solution doesn’t work.

Responding to your question, however: this is intended, and no, this will not be changed, as registering a custom handler routine is an odd request and prone to user error.

However, you can do the same in a supported way by monkey-patching AddEventHandler/RegisterNetEvent early in your resource:

fxmanifest.lua

client_scripts {
    '_first.lua',
    -- everything else
}

_first.lua

local origAddEventHandler = AddEventHandler

function AddEventHandler(event, cb)
    return origAddEventHandler(event, function(...)
        print('got event', event, source, ...)
        cb(...)
    end)
end

--- and similar for the callback to RegisterNetEvent, perhaps
1 Like

Hi

Behind this question there is indeed not another question, but the search for a solution to a need.

I am currently developing a fully object-oriented LUA framework, which will soon be released as open source. In its architecture, I am in a perspective to introduce Listeners (as on spigotmc) which have no direct control over the reception of events. The second need is to standardize the name of the events and to format them directly with the associated objects included in the framework (as on spigotmc), add new mechanics in the dispatch of the events through a chain of responsibility with several priority level (still like on spigotmc), and adding inside the chain auth system like an equivalent of JWT.

Unfortunately, it is impossible to have a reliable chain of responsibility without modifying the default disptach system. In addition, standardizing the name of certain events, and adapting the native FiveM events to the overcoat of the framework will force the loss of optimization by the processing that will have to be added! With the diagram below, we can see that the execution chain would really be simplified…

Modifying the dispatch function is also an advantage for a better integration for the cancellation of events (if we use the schema above, if event handler 1 calls the CancelEvent() function, event handler 2 does not will not be impacted according to the current dispatch system highlighted in the initial post [see the github link reference])

Finally, modifying the event dispatch system would be specific to a resource and its environment. It won’t impact other events or even server security. So I’m quite surprised that the shields raise so quickly in front of this question. It’s not the first time, and the last one was indeed justified, but this time I’m quite surprised. This question is only in a desire to bring new, more complete, more complex and more specific tools to the community… but over time, it becomes really demotivating when, each time a modification/improvement /additions is proposed, it is refused without taking into account the optimizations & possibility that it could bring to the community.

I highly doubt that.

This will not change without a convincing use case, and your use case is not convincing enough: there is no reason you can’t have a general wrapper event with a single name and route internally based on a field serialized with that event. If any issues occur as a result of this wrapper event’s existence that can be fixed by a scoped improvement to the platform, we’ll get to that when the time’s there.

Similarly, it seems like you’re overcomplicating things a lot, almost making up problems for the sake of making up problems. This ‘CancelEvent’ concern of yours, have you even tested or demonstrated it? In fact, if you have a custom event system, why would you not be able to also implement custom cancelation?

Instead of ‘bringing new, more complex tools’ by making a parallel API/ecosystem of your own (and then expecting us to welcome it with open arms and make random changes to facilitate it without any second thought, being startled when this is met with any resistance), why not suggest changes to the platform itself that fix whatever it is you’re running into regarding expressiveness?

There’s already ‘auth system’ in the platform (and I don’t see the need for ‘equivalent of JWT’ for stuff that works in-process), ‘priority level’ (ordered event handlers?) has been proposed a few times and had a prototype implementation, and none of this would need any reimplemented API to work at all…

So allowing resources to have their own dispatch engine will prone user error…

And monkey-patch does not lead devs to make errors or incompatibilities between scripts wich would be depedents on multiple other scripts ?? Let me really doubts about the magic of monkey-patch… just take a look, as exemple, to the ruby on rails community… a big part of the community make a lot’s of monkey-patch and it’s have lead to really really bad practices…

and in an other post you have said that :

So why pushing for monkey-patch when it’s not a way to get rid of low-quality code ?

I’m agree that’s could be a solution, but you’ll loose the possibility to make easy way to consume “open events” wich could work like a public API and be used without importing files from the resource.

I think you already knew what a chain of responsability is, so why make that remark? it does not add anything to the debate except to disperse us on other things…

'Cause the final target is not to make the framework compatible only on FiveM but allow to script wich are use the framework as dependencies to be portable accross game, like LibertyM and RedM without having to change any natives inside your own script, but only the version of the framework… it could also give the possibility for people to migrate servers from GTA5 to GTA6 if in the futur (wich is not, and i’ll give you it, in the next years) by making a specific version for it with it’s specific natives.

In other languages, there is plainty of exemple of frameworks wich have been the source of evolution into the runtime itself, like in C++ with Boost, in Php with Symfony Laravel and more…

So tell me how to implement it for securing events ? 'cause, actually, there is no internal way to really secures events without make over-processing wich will lead to unoptimized resources.

And where is the documentation about it ? 'cause, it’s because i’ve seen nothing about that in doc and natives that i was thinking about implementing it. So why using arguments about something that’s not communicate to the community ?

In this case… we are making a huge debat for allow resources to handle and dispatching events by themself in there own limitated scope. So if for you it’s useless, explain me how i can make a micro-script wich is listening for all events name wich is triggered for making stats and maybe look for indesirable events ? 'cause i’m pretty interested to see you implementation with the current possibilities.