Quick note on using built-in ACL/security

Ever since the built-in ACL system exists (add_ace and similar), it has somehow not seen people use it to its full potential, often adding dependencies on ‘frameworks’ to resources solely in order to check if a player is currently on a particular ‘job’ in said ‘framework’.

A lesser-known feature of the ACL system is the ability to have its configuration defined at runtime (in fact, there’s no persistence layer at all – the expectation has been for the community to build one), allowing you to do stuff as follows for example:

# server.cfg, required for access to ExecuteCommand
add_ace resource.myframework command.add_principal allow
add_ace resource.myframework command.remove_principal allow
// server-side code in myframework
on('myframework:jobAssigned', (source, job) => {
    ExecuteCommand(`add_principal "player.${source}" "job.${job}"`);

on('playerDropped', () => {
    const source = source;
    for (const job of myfw.getPlayerJobs(source)) {
        ExecuteCommand(`remove_principal "player.${source}" "job.${job}"`);

… and then a resource that one would want to add a job check to – or a chat mode’s seObject, or an existing resource – can just check for the job.mechanic privilege using native commands such as IsPlayerAceAllowed, without taking a dependency on myframework or any of its inner workings.

Using modified scenario files on FiveM

A forum post has been written detailing how to use modified scenarios on FiveM servers. The gist of the post is as follows:

However, what should work is registering a replacement scenario point manifest:

  1. take sp_manifest.#mt from update:/%platform%/levels/gta5/ from 1604 if you use it! if you use the 2189 one on 1604 you’ll crash with ERR_STR_PACK_2 as island scenarios don’t exist!, (contents of, as XML)
  2. specify it as data file:
    file 'sp_manifest.ymt'
    -- SCENARIO_POINTS_FILE may work, too
    data_file 'SCENARIO_POINTS_OVERRIDE_FILE' 'sp_manifest.ymt'
  3. edit it:
    <Item type="CScenarioPointRegionDef">
      <Name>compcache:/test_ymt/countryside_ne</Name> <!-- apparently VFSRagePackfile doesn't support RSC registration, so we use `compcache` instead of `resources` here -->
       <min x="577.9417" y="-2190.842" z="1.645161" />
       <max x="2970.658" y="6642.504" z="355.7393" />
  4. make sure file 'countryside_ne.ymt' is in your resource’s stream/ folder
  5. yay!

FYI: FiveM and RedM support raw .ymap/.ytyp files

For a while now, you’ve been able to use XML-format .ytyp/.ymap files in FiveM and RedM, without doing a conversion between XML and PSO/RSC format: just make sure the .xml file is just named mh1_01.ymap without any extra extension, and it should be parsed and used fine.

Note that these are loaded using the game parser, so this may behave differently in some ways from CodeWalker/OpenIV’s parsers.

Routing buckets: split game state

Server versions from pipeline ID 3245 and above have added a ‘routing bucket’ functionality, which is similar in concept to the ‘dimension’ or ‘virtual world’ functionality seen in prior non-Rockstar GTA network implementations.

For those unaware or lazy to search, one can assign a player or entity to a routing bucket, and they will only see entities (and players) that belong to the same routing bucket. In addition to that, each routing bucket will have its own ‘world grid’ for determining population owners, so even if you have population enabled, you’ll notice nothing unusual at all when using routing buckets.

Example use cases include:

  • Multi-mode servers where you want to have different games go on without affecting other games
  • Session/party systems
  • ‘Character screen’ being instanced differently from gameplay going on

Example use cases do explicitly not include interiors. Interiors should be using the traditional ‘conceal’ native functions, or the future support for 3D-scoped routing policy, which will also allow specifying any ‘instanced’ zone for MMO-style servers so a server can have a map area ‘dedicated’ to a player/party on a mission but still be able to see everything going on outside that zone.

See the linked timestamp in this GTA Online trailer to see why interiors should not be handled using this support in GTA V, where this was fine in GTA3 series titles because they did not have any interiors looking outwards.

The natives to use are as follows:

Note that these natives require OneSync to be ‘on’, not set to ‘legacy’ mode, and at this time might still route game events such as explosions and projectiles – this will be fixed in a near-future server version, as will support for sending network events to a specific routing bucket only.

CitizenFX C# templates are fixed

Since the earlier release of the CitizenFX C# templates, people have reported that certain built-in language types did not work, leading to vague errors such as '' is not a type supported by the compiler or such.

It took a while, but these should be fixed as of version 0.2.2 of the C# templates/SDK/framework packages, and these should now be usable for writing client code with compile-time checks for APIs available to the client-side subset framework.

A quick note about OneSync server-side persistence

Starting at server build 2689 (unless backed out in a later build), when using OneSync, there’s a few differences regarding entity lifetime compared to before.

  • Entities that are owned by a script (not marked as no-longer-needed, or re-assigned as mission entity) will now be able to be in an ‘unowned’ state in which the server is the owner of the entity. This happens when no player is having the entity in scope (as in – the entity is out of range of any player), and this state ends when it goes in scope for a player.
  • Script ownership is now correctly synced across the board. No longer does the owning script ID vanish when an entity migrates or is recreated. This should fix a lot of cases of mission entities getting deleted anyway.
  • Faraway entities are no longer controlled by their original owner. This means that any entity that would be out of scope will be culled and migrated/disowned. It might lead to a small number of script compatibility issues, but in return a lot of cases of unenterable vehicles (because the owner is too far and doesn’t know you) especially with Infinity/Beyond modes should be fixed.
  • Entities that aren’t owned by a script get reassigned and, when impossible, culled when out of scope. This is a difference from the old behavior where this was up to the game behavior of the owning client. Typically, the owning client would have cleaned up non-script entities early anyway, so this should not be a significant difference.

In addition to these changes, a number of improvements to ‘entity RPC’ are planned to allow for more robust server-side entity creation/initial configuration of entities by taking advantage of this ‘unowned entity’ state, resolving a large number of issues with current server-side CREATE_VEHICLE/… calls.

Try the new CitizenFX C# templates for FiveM

We’ve recently published the CitizenFX.Templates package on NuGet, which includes a nice template for making a fully C#-based resource using the latest recommendations. The docs will be updated whenever more people confirm this works and report some feedback as to this, but for now here’s the steps to set it up:

dotnet new -i CitizenFX.Templates
mkdir MyResource
cd MyResource
dotnet new cfx-resource

You’ll find helpful instructions afterwards in the generated README.md.

Uploading photos from in-game to the Cfx.re Gallery

Recent builds of FiveM have added backing functionality to the photo gallery feature in the pause menu. This guide shows how to upload your photos to the Cfx.re Snapmatic section on the forums.

  1. Make sure you have a photo camera resource that uses photo commands to save a gallery photo. An example resource would e.g. be Xinerki’s ‘Cellphone Camera‘ resource, instructions for which can be found in the topic.
  2. Sign in and link your Cfx.re forum account in the main menu of FiveM.
  3. Go to the pause menu in a server (or a local game), and go to Gallery, and press Enter/A.
  4. Select a photo to upload, assuming you have a few. You can also press Enter/A to view/confirm and change the title.
  5. Press the ‘Upload to Social Club’ button as marked in the bottom of the screen.
  6. Say ‘Yes’.
  7. Wait a while.
  8. You’ll see your image uploaded on the forums!

Using the new console key bindings

You’re able to define keyboard bindings in a new way, as originally detailed in the 2018 design document “Configuration & Input – Redesigned“.

Here’s a sample snippet of a simple ‘hands up’ binding:

local handsUp = false

    while true do

        if handsUp then
            TaskHandsUp(PlayerPedId(), 250, PlayerPedId(), -1, true)

RegisterCommand('+handsup', function()
    handsUp = true
end, false)

RegisterCommand('-handsup', function()
    handsUp = false
end, false)

RegisterKeyMapping('+handsup', 'Hands Up', 'keyboard', 'i')
RegisterKeyMapping('say hi', 'Say hi', 'keyboard', 'o')
User-editable bindings.

These bindings will be editable by the user in the ‘key bindings’ option (only 1 binding per command yet, no secondary binding), and depending on user demand we’ll add a helper for computing the right hashes to use with ~INPUT_~-style display as well for help hints and similar.

In addition to that, a plethora of new console commands are added to the client F8 console, an example is below:

// bind a key to toggle the safe zone to an offscreen size and back
bind KEYBOARD F3 "+vstr hideHud showHud"
seta "hideHud" "profile_safezoneSize 500"
seta "showHud" "profile_safezoneSize 7"

// list all bindings

// bind for a specific resource (similar to RegisterKeyMapping)
rbind runcode keyboard o "say hi"

// unbind
unbind keyboard f3

// set the volume way above the usual max
profile_sfxVolume 50

// ear rape?
profile_sfxVolume 9000

// toggle a variable
toggle strmem

// toggle a variable between two values
toggle con_miniConChannels * minicon:*

// see cmdlist to view all new and existing variables and commands

… and the fxd:/fivem.cfg (%appdata%\citizenfx) file contains a lot of additional user settings now in a readable format.

Optimizing resource downloads using a caching proxy

Server builds starting at pipeline ID 1679 added the ability to configure the fileServer field used for resource downloading using a set of commands:

# Set the file server for the specified resource regex.
# The URL should *not* end with a slash.
fileserver_add ".*" ""

# Remove the file server associated with a resource regex.
fileserver_remove ".*"

# List all registered file server patterns.

# Old command, but **required** to not get corrupted cache entries.
adhesive_cdnKey "someSecurePassphrase"

There’s currently no cache invalidation logic based on hashes (this’ll need yet another server update due to the file server not ignoring query strings + a client update), so make sure to clear your proxy’s cache before you modify/restart a resource.

Here’s an example NGINX configuration for setting this up (but you should, for example, run this behind yet another proxy which offers HTTP/2 over TLS, or otherwise set this up properly – we’re expecting the community to provide fleshed-out examples on the forums):


proxy_cache_path /srv/cache levels=1:2 keys_zone=assets:48m max_size=10g ;
log_format asset '$remote_addr - [$time_local] "$request" $status $body_bytes_sent $upstream_cache_status';

server {
        listen 80;

        location /files/ {
                access_log /dev/stdout asset;
                add_header X-Cache-Status $upstream_cache_status;
                proxy_cache_lock on;
                proxy_pass $REMOTE$request_uri;
                proxy_cache assets;
                proxy_cache_valid 1y;
                proxy_cache_key $request_uri$is_args$args;


FROM nginx:alpine
COPY default.template /etc/nginx/conf.d/default.template
CMD sh -c "envsubst \"`env | awk -F = '{printf \" \\\\$%s\", $1}'`\" < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"

Start command

docker build -t fxproxy .
docker run -d --name=fxproxy -e REMOTE= -p 80:80 -v $PWD/cache:/srv/cache fxproxy