Turfwar/server/atm_access.lua

105 lines
2.9 KiB
Lua

-- server/atm_access.lua
print("^2[turfwar]^7 atm_access.lua loaded (server-side gatekeeper)")
Config = Config or {}
Config.Finance = Config.Finance or {}
local USE_RADIUS = tonumber(Config.Finance.ATM_USE_RADIUS) or 1.8
local TTL_MS = tonumber(Config.Finance.ATM_SESSION_TTL_MS) or 15000
local sessions = {}
local function dist3(a, b)
local dx = (a.x - b.x)
local dy = (a.y - b.y)
local dz = (a.z - b.z)
return math.sqrt(dx*dx + dy*dy + dz*dz)
end
local function newToken()
return ("%08x%08x"):format(math.random(0, 0xffffffff), math.random(0, 0xffffffff))
end
local function getPlayerCoords(src)
local ped = GetPlayerPed(src)
if not ped or ped == 0 then return nil end
local c = GetEntityCoords(ped)
return { x = c.x, y = c.y, z = c.z }
end
RegisterNetEvent("turfwar:atm:open", function(payload)
local src = source
if type(payload) ~= "table" then
TriggerClientEvent("turfwar:atm:openDenied", src, "bad_payload")
return
end
local x, y, z = tonumber(payload.x), tonumber(payload.y), tonumber(payload.z)
local model = payload.model
if not x or not y or not z then
TriggerClientEvent("turfwar:atm:openDenied", src, "bad_coords")
return
end
local okModel = false
for _, m in ipairs(Config.Finance.ATM_MODELS or {}) do
if m == model then okModel = true break end
end
if not okModel then
TriggerClientEvent("turfwar:atm:openDenied", src, "bad_model")
return
end
local pc = getPlayerCoords(src)
if not pc then
TriggerClientEvent("turfwar:atm:openDenied", src, "no_ped")
return
end
local atmC = { x = x, y = y, z = z }
if dist3(pc, atmC) > (USE_RADIUS + 0.75) then
TriggerClientEvent("turfwar:atm:openDenied", src, "too_far")
return
end
local token = newToken()
sessions[src] = {
token = token,
expires = GetGameTimer() + TTL_MS,
atm = { x = x, y = y, z = z, model = model }
}
TriggerClientEvent("turfwar:atm:openGranted", src, token)
end)
local function RequireATM(src, token, verbose)
local s = sessions[src]
if not s then return false, "no_session" end
if token ~= s.token then return false, "bad_token" end
if GetGameTimer() > (s.expires or 0) then
sessions[src] = nil
return false, "expired"
end
local pc = getPlayerCoords(src)
if not pc then return false, "no_ped" end
local atmC = { x = s.atm.x, y = s.atm.y, z = s.atm.z }
if dist3(pc, atmC) > (USE_RADIUS + 0.75) then
if verbose then
print(("^1[ATM BLOCK]^7 src=%d moved away from ATM"):format(src))
end
sessions[src] = nil
return false, "moved_away"
end
return true
end
exports("RequireATM", RequireATM)
AddEventHandler("playerDropped", function()
sessions[source] = nil
end)