[Tutorial] Mastering Event-Driven Architecture

Mastering Event-Driven Architecture

Let’s talk about some good patterns for bug-free programming.

Imagine that you have Inventory in your game mode.
You should store player items on the server-side/database to avoid hacking.

Now let’s look at the example code below:

Inventory = { }

function Inventory.ConsumeFood()
    TriggerServerEvent('gamemode:consumeFood') -- We should check if a player has enough food etc.
end

AddEventHandler('gamemode:onFoodConsumed', function(consume)
    if not consume then return end -- 'consume' is a boolean flag which indicates if a player can actually consume food

    Inventory.DoConsumeFood() -- Actual stuff like restoring player health etc.
end)

This code has a few potential issues.
Let’s fix it step by step.

This code allows to consume food multiple times at once.
The fix is really easy - just use a boolean flag to check if the consuming process is already in progress.

Inventory.IsConsumingFood = false

function Inventory.ConsumeFood()
    if Inventory.IsConsumingFood then
        return false
    end

    Inventory.IsConsumingFood = true
    TriggerServerEvent('gamemode:consumeFood')

    return true -- You could even return a boolean to check if it was actually triggered
end

But what if a player has died while we’re waiting for the server result?
You should always think about events and any functions with Citizen.Wait(ms) call in asynchronous way.
As for this problem, you should not forget to reset your consuming boolean flag at appropriate place.

AddEventHandler('playerSpawned', function()
    Inventory.CancelConsuming()
end)

-- It is better to use a helper function for future items like Bandages, Drinks etc.
function Inventory.CancelConsuming()
    Inventory.IsConsumingFood = false
end

AddEventHandler('gamemode:onFoodConsumed', function(consume)
    if not consume or not Inventory.IsConsumingFood then return end

    Inventory.DoConsumeFood()
end)

It would be also a good idea to actually cancel consuming on the server-side.

function Inventory.CancelConsuming()
    if Inventory.IsConsumingFood then
        TriggerServerEvent('gamemode:cancelConsumingFood')
    end

    Inventory.IsConsumingFood = false
end

And yes - that is all for now.

Please leave comments so I could add more detailed information or even write another tutorial.
Thank you for your attention!

Read about FiveM events

8 Likes

Thanks for this brief tutorial. I hope you intend to do more like this. :+1:

1 Like

This is really helpful. Can you write one that going into more depth on using servers?

Post here your questions if you want to see more tutorials.