[HELP/SUGGESTION] Run a resource in a host-clients manner to allow for global network IDs of entities

From what I’ve observed from this and similar threads, the problem with NetworkGetNetworkIdFromEntity is that the ID returned from the function is bound to the script that created the entity. When I spawn a vehicle with CreateVehicle, obtain its ID and then restart the resource, the ID stops being valid and cannot be used. Also calling SetEntityAsMissionEntity can help with reobtaining the correct network ID.

However, the problem si that the script itself is not synchronised. Although the game supports running scripts in a manner where one player is host and the others are clients, a FiveM resource is always run with the current player as the host, i.e. locally. NetworkIsHostOfThisScript always returns true, no matter whether the player is the actual host of the session or not. The instance of the script is unique for each player, and thus the script is not synchronised.

It seems that if a player (session host) started a script on his own, possibly from a resource that is only made to spawn entities and return their IDs (a “pool resource”), the other players would be clients of the script and be able to access correct entities from functions like NetworkGetEntityFromNetworkId.

The problem is that it’s apparently impossible at the moment to start a script in this manner. I’ve tried to use functions like RequestScript, StartNewScript etc. using my resource name, but it apparently cannot find them.

Are my assumptions correct? Is it possible to run a resource in this manner, to sychronize the entity pool over all players? If not, I suggest it be added (possibly a manifest instruction like hosted_client_script or something), or a way to obtain the actual synchronisation ID of an entity - I know it’s not the network ID, because that’s local, but there is certainly a way the network protocol represents an entity when exchanging synchronisation information with other players, and this ID would be able to be used to identify an entity in a session.

2 Likes

Have you tried using the (undocumented) 05cfa83c-a124-4cfa-a768-c24a5811d8f9 resource manifest version?

The change log seems to be:

  • Scripts will now be registered as a game network script. This is required for networking entities.

Thank you, it works. Are there any other equally cool undocumented features?

See https://github.com/citizenfx/fivem/blob/master/ext/natives/codegen_cfx_natives.lua for example, some script commands haven’t been formally announced but do exist.

Thank you. How do I use functions like FIND_NEXT_PED?

Edit: Found out how to use it. I am sure someone will find a use for this.

I’m not sure if this is better posted here or in one of the many recent script problem solving threads such as this active one, but it seems to me a more general discussion is needed about networked entities and the resource manifest ‘05cfa83c-a124-4cfa-a768-c24a5811d8f9’ mentioned above. This is the post where @IllidanS4 raised the issue in a general way and where the manifest was first mentioned.

My application is a spotlight modification for @mraes heli mod. The heli pilot identifies a target vehicle which is then passed to clients in order to draw a spotlight on the target. It seems the optimal way to do this would be using netid <-> entity conversions so I tried this with the above manifest but I got some curious results.

My testing was simple: two players join a server, hop in the same heli and test the targeting system. Then they switch pilot / co-pilot positions and retest. Each client periodically checks NetworkGetHostOfThisScript and traces whether or not the pilot gets an initial netID from the spotlight target vehicle and whether the remote (co-pilot) client receives it and can convert the netID back to a global entityID. NOTE, in this testing these targets are generally computer npc vehicles not vehicles created by a player.

With the older manifests neither player can get a netID from the target and NetworkIsHostOfThisScript does not seem to work. With the new manifest, these are more successful but there is still inconsistency with netID <-> entity functionality. This may be expected behaviour of the networking codebase but if so I would like to understand it more.

First, only the script host according to NetworkGetHostOfThisScript can get a netID from the target when he is pilot. And I believe even this works only when I use SetEntityAsMissionEntity on the target. I have tried every other network native I could find to request/reserve/migrate the entityID/netID that is the target vehicle and even all of them combined make no difference for me without the mission entity native. SetEntityAsMissionEntity is both necessary and sufficient by itself to ensure netID <-> entity convertibility but again only for the script host.

Second, the script host according to NetworkGetHostOfThisScript changes suddenly and unexpectedly. Heli takes off and shortly after the host might change from pilot to co-pilot, and as soon as this happens the non-script-host pilot can no longer resolve netIDs. If the new script host co-pilot takes over as pilot he can resolve netIDs.

Third, even when the pilot is script host and the target is set as mission entity, there was one reproducible situation where he cannot get a netID. When the target changes, and my target_vehicle variable gets set to the new target, suddenly you can’t get a netID (returns 0) from the same target_vehicle variable that normally would resolve. Just to be clear, the exact same code that sets target_vehicle works to obtain a netID (for the script host) when target_vehicle has been nil for some time, but does not work if there is a current non-nil target_vehicle which is being updated. I wondered if it was simply a matter of time required to sync/reset/register an object on the network. But when I added some lines to pause 2-3 seconds and retry VehToNet but the script-host pilot was still unable to get a netID.

Can anyone explain these results? And is there a way to get around the script host issue to more reliably obtain netIDs or am I doing something completely wrong?