Explorer
KNOW-PAT-107

FiveM - Door Lock Double Doors : AddDoorToSystem, hash-based sync, encodeData JSON

Domaine
fivem
Type
pattern
Priorité
P2

Parent : [[INDEX-FIVEM-GAMEPLAY]]

FiveM - Door Lock Double Doors : AddDoorToSystem, hash-based sync, encodeData JSON

Problème

Les portes dans GTA V doivent être synchronisées entre tous les joueurs. Les double portes (double doors) nécessitent la gestion de deux entités séparées avec le même état.

Solution

Gestion de portes simples et doubles avec AddDoorToSystem, DoorSystemSetDoorState, hash-based identification, encodeData JSON pour sync client-serveur.

-- client.lua
local function createDoor(door)
    local double = door.doors
    if double then
        for i = 1, 2 do
            AddDoorToSystem(
                double[i].hash,
                double[i].model,
                double[i].coords.x,
                double[i].coords.y,
                double[i].coords.z,
                false,
                false,
                false
            )
            DoorSystemSetDoorState(double[i].hash, door.state, false, false)
        end
    else
        AddDoorToSystem(
            door.hash,
            door.model,
            door.coords.x,
            door.coords.y,
            door.coords.z,
            false,
            false,
            false
        )
        DoorSystemSetDoorState(door.hash, door.state, false, false)
    end
end

-- server.lua : sync via state bags ou events
RegisterNetEvent('ox_doorlock:setState')
AddEventHandler('ox_doorlock:setState', function(doorId, state)
    local src = source
    local door = Doors[doorId]
    if not door then return end
    
    -- Vérification permission (job, item, lockpick)
    if not CanToggleDoor(src, door) then
        TriggerClientEvent('ox_lib:notify', src, { type = 'error', description = 'Accès refusé' })
        return
    end
    
    door.state = state
    
    -- Sync à tous les clients
    TriggerClientEvent('ox_doorlock:updateState', -1, doorId, state, door)
    
    -- Persistence optionnelle
    if door.persist then
        MySQL.update('UPDATE doorlock SET state = ? WHERE id = ?', { state and 1 or 0, doorId })
    end
end)

-- Encode/Decode pour transmission
function EncodeDoorData(door)
    return json.encode({
        id = door.id,
        state = door.state,
        coords = door.coords,
        model = door.model,
        doors = door.doors -- nil si simple
    })
end

Pourquoi

  • AddDoorToSystem est le native GTA pour la sync automatique entre joueurs
  • Hash-based évite les conflits de coordonnées (deux portes proches)
  • Double door loop évite la duplication de code

Quant l'utiliser

  • Systèmes de fermeture de portes (police, banques, maisons)
  • Lockpicking, keycards, job-based access

Quand NE PAS l'utiliser

  • Portes intérieures d'appartements uniques (pas besoin de sync globale)

Exemples

Correct

-- Config porte avec permissions
Config.Doors = {
    {
        id = 'police_main',
        model = `v_ilev_ph_door01`,
        coords = vector3(434.7, -982.0, 30.7),
        state = true, -- fermé
        permissions = {
            jobs = { police = true, sheriff = true },
            items = { 'police_keycard' }
        },
        persist = true
    },
    {
        id = 'bank_vault',
        doors = {
            {
                hash = `bank_vault_left`,
                model = `v_ilev_bk_vaultdoor`,
                coords = vector3(254.1, 225.2, 101.9)
            },
            {
                hash = `bank_vault_right`,
                model = `v_ilev_bk_vaultdoor`,
                coords = vector3(254.1, 225.2, 101.9)
            }
        },
        state = true,
        permissions = {
            jobs = { police = 3 }, -- grade 3 minimum
            items = { 'bank_vault_key' }
        }
    }
}

Incorrect

-- Toggle porte sans hash → peut affecter la mauvaise porte
RegisterNetEvent('door:toggle')
AddEventHandler('door:toggle', function(doorCoords)
    local door = GetClosestObjectOfType(doorCoords.x, doorCoords.y, doorCoords.z, 1.0, -1, false, false, false)
    if DoesEntityExist(door) then
        -- Affecte toutes les portes proches avec le même model
        FreezeEntityPosition(door, not IsEntityPositionFrozen(door))
    end
end)

Références

  • ox_doorlock/server/main.lua L16-50
  • ox_doorlock/client/main.lua L7-29
  • ox_doorlock/config.lua L1-39