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
AddDoorToSystemest 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