599 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			599 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local QBCore = exports['qb-core']:GetCoreObject()
 | 
						|
local Races = {}
 | 
						|
local AvailableRaces = {}
 | 
						|
local LastRaces = {}
 | 
						|
local NotFinished = {}
 | 
						|
 | 
						|
-- Functions
 | 
						|
 | 
						|
local function SecondsToClock(seconds)
 | 
						|
    seconds = tonumber(seconds)
 | 
						|
    local retval
 | 
						|
    if seconds <= 0 then
 | 
						|
        retval = "00:00:00";
 | 
						|
    else
 | 
						|
        local hours = string.format("%02.f", math.floor(seconds / 3600));
 | 
						|
        local mins = string.format("%02.f", math.floor(seconds / 60 - (hours * 60)));
 | 
						|
        local secs = string.format("%02.f", math.floor(seconds - hours * 3600 - mins * 60));
 | 
						|
        retval = hours .. ":" .. mins .. ":" .. secs
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function IsWhitelisted(CitizenId)
 | 
						|
    local retval = false
 | 
						|
    for _, cid in pairs(Config.WhitelistedCreators) do
 | 
						|
        if cid == CitizenId then
 | 
						|
            retval = true
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
    local Player = QBCore.Functions.GetPlayerByCitizenId(CitizenId)
 | 
						|
    local Perms = QBCore.Functions.GetPermission(Player.PlayerData.source)
 | 
						|
    if Perms == "admin" or Perms == "god" then
 | 
						|
        retval = true
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function IsNameAvailable(RaceName)
 | 
						|
    local retval = true
 | 
						|
    for RaceId, _ in pairs(Races) do
 | 
						|
        if Races[RaceId].RaceName == RaceName then
 | 
						|
            retval = false
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function HasOpenedRace(CitizenId)
 | 
						|
    local retval = false
 | 
						|
    for _, v in pairs(AvailableRaces) do
 | 
						|
        if v.SetupCitizenId == CitizenId then
 | 
						|
            retval = true
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function GetOpenedRaceKey(RaceId)
 | 
						|
    local retval = nil
 | 
						|
    for k, v in pairs(AvailableRaces) do
 | 
						|
        if v.RaceId == RaceId then
 | 
						|
            retval = k
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function GetCurrentRace(MyCitizenId)
 | 
						|
    local retval = nil
 | 
						|
    for RaceId, _ in pairs(Races) do
 | 
						|
        for cid, _ in pairs(Races[RaceId].Racers) do
 | 
						|
            if cid == MyCitizenId then
 | 
						|
                retval = RaceId
 | 
						|
                break
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function GetRaceId(name)
 | 
						|
    local retval = nil
 | 
						|
    for k, v in pairs(Races) do
 | 
						|
        if v.RaceName == name then
 | 
						|
            retval = k
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return retval
 | 
						|
end
 | 
						|
 | 
						|
local function GenerateRaceId()
 | 
						|
    local RaceId = "LR-" .. math.random(1111, 9999)
 | 
						|
    while Races[RaceId] ~= nil do
 | 
						|
        RaceId = "LR-" .. math.random(1111, 9999)
 | 
						|
    end
 | 
						|
    return RaceId
 | 
						|
end
 | 
						|
 | 
						|
-- Events
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:FinishPlayer', function(RaceData, TotalTime, TotalLaps, BestLap)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local AvailableKey = GetOpenedRaceKey(RaceData.RaceId)
 | 
						|
    local PlayersFinished = 0
 | 
						|
    local AmountOfRacers = 0
 | 
						|
    for _, v in pairs(Races[RaceData.RaceId].Racers) do
 | 
						|
        if v.Finished then
 | 
						|
            PlayersFinished = PlayersFinished + 1
 | 
						|
        end
 | 
						|
        AmountOfRacers = AmountOfRacers + 1
 | 
						|
    end
 | 
						|
    local BLap
 | 
						|
    if TotalLaps < 2 then
 | 
						|
        BLap = TotalTime
 | 
						|
    else
 | 
						|
        BLap = BestLap
 | 
						|
    end
 | 
						|
    if LastRaces[RaceData.RaceId] ~= nil then
 | 
						|
        LastRaces[RaceData.RaceId][#LastRaces[RaceData.RaceId]+1] =  {
 | 
						|
            TotalTime = TotalTime,
 | 
						|
            BestLap = BLap,
 | 
						|
            Holder = {
 | 
						|
                [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                [2] = Player.PlayerData.charinfo.lastname
 | 
						|
            }
 | 
						|
        }
 | 
						|
    else
 | 
						|
        LastRaces[RaceData.RaceId] = {}
 | 
						|
        LastRaces[RaceData.RaceId][#LastRaces[RaceData.RaceId]+1] =  {
 | 
						|
            TotalTime = TotalTime,
 | 
						|
            BestLap = BLap,
 | 
						|
            Holder = {
 | 
						|
                [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                [2] = Player.PlayerData.charinfo.lastname
 | 
						|
            }
 | 
						|
        }
 | 
						|
    end
 | 
						|
    if Races[RaceData.RaceId].Records ~= nil and next(Races[RaceData.RaceId].Records) ~= nil then
 | 
						|
        if BLap < Races[RaceData.RaceId].Records.Time then
 | 
						|
            Races[RaceData.RaceId].Records = {
 | 
						|
                Time = BLap,
 | 
						|
                Holder = {
 | 
						|
                    [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                    [2] = Player.PlayerData.charinfo.lastname
 | 
						|
                }
 | 
						|
            }
 | 
						|
            MySQL.update('UPDATE lapraces SET records = ? WHERE raceid = ?',
 | 
						|
                {json.encode(Races[RaceData.RaceId].Records), RaceData.RaceId})
 | 
						|
            TriggerClientEvent('qb-phone:client:RaceNotify', src, 'You have won the WR from ' .. RaceData.RaceName ..
 | 
						|
                ' disconnected with a time of: ' .. SecondsToClock(BLap) .. '!')
 | 
						|
        end
 | 
						|
    else
 | 
						|
        Races[RaceData.RaceId].Records = {
 | 
						|
            Time = BLap,
 | 
						|
            Holder = {
 | 
						|
                [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                [2] = Player.PlayerData.charinfo.lastname
 | 
						|
            }
 | 
						|
        }
 | 
						|
        MySQL.update('UPDATE lapraces SET records = ? WHERE raceid = ?',
 | 
						|
            {json.encode(Races[RaceData.RaceId].Records), RaceData.RaceId})
 | 
						|
        TriggerClientEvent('qb-phone:client:RaceNotify', src, 'You have won the WR from ' .. RaceData.RaceName ..
 | 
						|
            ' put down with a time of: ' .. SecondsToClock(BLap) .. '!')
 | 
						|
    end
 | 
						|
    AvailableRaces[AvailableKey].RaceData = Races[RaceData.RaceId]
 | 
						|
    TriggerClientEvent('qb-lapraces:client:PlayerFinishs', -1, RaceData.RaceId, PlayersFinished, Player)
 | 
						|
    if PlayersFinished == AmountOfRacers then
 | 
						|
        if NotFinished ~= nil and next(NotFinished) ~= nil and NotFinished[RaceData.RaceId] ~= nil and
 | 
						|
            next(NotFinished[RaceData.RaceId]) ~= nil then
 | 
						|
            for _, v in pairs(NotFinished[RaceData.RaceId]) do
 | 
						|
                LastRaces[RaceData.RaceId][#LastRaces[RaceData.RaceId]+1] = {
 | 
						|
                    TotalTime = v.TotalTime,
 | 
						|
                    BestLap = v.BestLap,
 | 
						|
                    Holder = {
 | 
						|
                        [1] = v.Holder[1],
 | 
						|
                        [2] = v.Holder[2]
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            end
 | 
						|
        end
 | 
						|
        Races[RaceData.RaceId].LastLeaderboard = LastRaces[RaceData.RaceId]
 | 
						|
        Races[RaceData.RaceId].Racers = {}
 | 
						|
        Races[RaceData.RaceId].Started = false
 | 
						|
        Races[RaceData.RaceId].Waiting = false
 | 
						|
        table.remove(AvailableRaces, AvailableKey)
 | 
						|
        LastRaces[RaceData.RaceId] = nil
 | 
						|
        NotFinished[RaceData.RaceId] = nil
 | 
						|
    end
 | 
						|
    TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:CreateLapRace', function(RaceName)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
 | 
						|
    if IsWhitelisted(Player.PlayerData.citizenid) then
 | 
						|
        if IsNameAvailable(RaceName) then
 | 
						|
            TriggerClientEvent('qb-lapraces:client:StartRaceEditor', source, RaceName)
 | 
						|
        else
 | 
						|
            TriggerClientEvent('QBCore:Notify', source, 'There is already a race with this name.', 'error')
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', source, 'You have not been authorized to race\'s to create.', 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:JoinRace', function(RaceData)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local RaceId = RaceData.RaceId
 | 
						|
    local AvailableKey = GetOpenedRaceKey(RaceId)
 | 
						|
    local CurrentRace = GetCurrentRace(Player.PlayerData.citizenid)
 | 
						|
    if CurrentRace ~= nil then
 | 
						|
        local AmountOfRacers = 0
 | 
						|
        local PreviousRaceKey = GetOpenedRaceKey(CurrentRace)
 | 
						|
        for _, _ in pairs(Races[CurrentRace].Racers) do
 | 
						|
            AmountOfRacers = AmountOfRacers + 1
 | 
						|
        end
 | 
						|
        Races[CurrentRace].Racers[Player.PlayerData.citizenid] = nil
 | 
						|
        if (AmountOfRacers - 1) == 0 then
 | 
						|
            Races[CurrentRace].Racers = {}
 | 
						|
            Races[CurrentRace].Started = false
 | 
						|
            Races[CurrentRace].Waiting = false
 | 
						|
            table.remove(AvailableRaces, PreviousRaceKey)
 | 
						|
            TriggerClientEvent('QBCore:Notify', src, 'You were the only one in the race, the race had ended', 'error')
 | 
						|
            TriggerClientEvent('qb-lapraces:client:LeaveRace', src, Races[CurrentRace])
 | 
						|
        else
 | 
						|
            AvailableRaces[PreviousRaceKey].RaceData = Races[CurrentRace]
 | 
						|
            TriggerClientEvent('qb-lapraces:client:LeaveRace', src, Races[CurrentRace])
 | 
						|
        end
 | 
						|
        TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
    end
 | 
						|
    Races[RaceId].Waiting = true
 | 
						|
    Races[RaceId].Racers[Player.PlayerData.citizenid] = {
 | 
						|
        Checkpoint = 0,
 | 
						|
        Lap = 1,
 | 
						|
        Finished = false
 | 
						|
    }
 | 
						|
    AvailableRaces[AvailableKey].RaceData = Races[RaceId]
 | 
						|
    TriggerClientEvent('qb-lapraces:client:JoinRace', src, Races[RaceId], AvailableRaces[AvailableKey].Laps)
 | 
						|
    TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
    local creatorsource = QBCore.Functions.GetPlayerByCitizenId(AvailableRaces[AvailableKey].SetupCitizenId).PlayerData
 | 
						|
                              .source
 | 
						|
    if creatorsource ~= Player.PlayerData.source then
 | 
						|
        TriggerClientEvent('qb-phone:client:RaceNotify', creatorsource,
 | 
						|
            string.sub(Player.PlayerData.charinfo.firstname, 1, 1) .. '. ' .. Player.PlayerData.charinfo.lastname ..
 | 
						|
                ' the race has been joined!')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:LeaveRace', function(RaceData)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local RaceName
 | 
						|
    if RaceData.RaceData ~= nil then
 | 
						|
        RaceName = RaceData.RaceData.RaceName
 | 
						|
    else
 | 
						|
        RaceName = RaceData.RaceName
 | 
						|
    end
 | 
						|
    local RaceId = GetRaceId(RaceName)
 | 
						|
    local AvailableKey = GetOpenedRaceKey(RaceData.RaceId)
 | 
						|
    local creatorsource = QBCore.Functions.GetPlayerByCitizenId(AvailableRaces[AvailableKey].SetupCitizenId).PlayerData
 | 
						|
                              .source
 | 
						|
    if creatorsource ~= Player.PlayerData.source then
 | 
						|
        TriggerClientEvent('qb-phone:client:RaceNotify', creatorsource,
 | 
						|
            string.sub(Player.PlayerData.charinfo.firstname, 1, 1) .. '. ' .. Player.PlayerData.charinfo.lastname ..
 | 
						|
                ' the race has been delivered!')
 | 
						|
    end
 | 
						|
    local AmountOfRacers = 0
 | 
						|
    for _, _ in pairs(Races[RaceData.RaceId].Racers) do
 | 
						|
        AmountOfRacers = AmountOfRacers + 1
 | 
						|
    end
 | 
						|
    if NotFinished[RaceData.RaceId] ~= nil then
 | 
						|
        NotFinished[RaceData.RaceId][#NotFinished[RaceData.RaceId]+1] = {
 | 
						|
            TotalTime = "DNF",
 | 
						|
            BestLap = "DNF",
 | 
						|
            Holder = {
 | 
						|
                [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                [2] = Player.PlayerData.charinfo.lastname
 | 
						|
            }
 | 
						|
        }
 | 
						|
    else
 | 
						|
        NotFinished[RaceData.RaceId] = {}
 | 
						|
        NotFinished[RaceData.RaceId][#NotFinished[RaceData.RaceId]+1] = {
 | 
						|
            TotalTime = "DNF",
 | 
						|
            BestLap = "DNF",
 | 
						|
            Holder = {
 | 
						|
                [1] = Player.PlayerData.charinfo.firstname,
 | 
						|
                [2] = Player.PlayerData.charinfo.lastname
 | 
						|
            }
 | 
						|
        }
 | 
						|
    end
 | 
						|
    Races[RaceId].Racers[Player.PlayerData.citizenid] = nil
 | 
						|
    if (AmountOfRacers - 1) == 0 then
 | 
						|
        if NotFinished ~= nil and next(NotFinished) ~= nil and NotFinished[RaceId] ~= nil and next(NotFinished[RaceId]) ~=
 | 
						|
            nil then
 | 
						|
            for _, v in pairs(NotFinished[RaceId]) do
 | 
						|
                if LastRaces[RaceId] ~= nil then
 | 
						|
                    LastRaces[RaceId][#LastRaces[RaceId]+1] = {
 | 
						|
                        TotalTime = v.TotalTime,
 | 
						|
                        BestLap = v.BestLap,
 | 
						|
                        Holder = {
 | 
						|
                            [1] = v.Holder[1],
 | 
						|
                            [2] = v.Holder[2]
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                else
 | 
						|
                    LastRaces[RaceId] = {}
 | 
						|
                    LastRaces[RaceId][#LastRaces[RaceId]+1] = {
 | 
						|
                        TotalTime = v.TotalTime,
 | 
						|
                        BestLap = v.BestLap,
 | 
						|
                        Holder = {
 | 
						|
                            [1] = v.Holder[1],
 | 
						|
                            [2] = v.Holder[2]
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
        Races[RaceId].LastLeaderboard = LastRaces[RaceId]
 | 
						|
        Races[RaceId].Racers = {}
 | 
						|
        Races[RaceId].Started = false
 | 
						|
        Races[RaceId].Waiting = false
 | 
						|
        table.remove(AvailableRaces, AvailableKey)
 | 
						|
        TriggerClientEvent('QBCore:Notify', src, 'You were the only one in the race.The race had ended.', 'error')
 | 
						|
        TriggerClientEvent('qb-lapraces:client:LeaveRace', src, Races[RaceId])
 | 
						|
        LastRaces[RaceId] = nil
 | 
						|
        NotFinished[RaceId] = nil
 | 
						|
    else
 | 
						|
        AvailableRaces[AvailableKey].RaceData = Races[RaceId]
 | 
						|
        TriggerClientEvent('qb-lapraces:client:LeaveRace', src, Races[RaceId])
 | 
						|
    end
 | 
						|
    TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:SetupRace', function(RaceId, Laps)
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    if Races[RaceId] ~= nil then
 | 
						|
        if not Races[RaceId].Waiting then
 | 
						|
            if not Races[RaceId].Started then
 | 
						|
                Races[RaceId].Waiting = true
 | 
						|
                AvailableRaces[#AvailableRaces+1] = {
 | 
						|
                    RaceData = Races[RaceId],
 | 
						|
                    Laps = Laps,
 | 
						|
                    RaceId = RaceId,
 | 
						|
                    SetupCitizenId = Player.PlayerData.citizenid
 | 
						|
                }
 | 
						|
                TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
                SetTimeout(5 * 60 * 1000, function()
 | 
						|
                    if Races[RaceId].Waiting then
 | 
						|
                        local AvailableKey = GetOpenedRaceKey(RaceId)
 | 
						|
                        for cid, _ in pairs(Races[RaceId].Racers) do
 | 
						|
                            local RacerData = QBCore.Functions.GetPlayerByCitizenId(cid)
 | 
						|
                            if RacerData ~= nil then
 | 
						|
                                TriggerClientEvent('qb-lapraces:client:LeaveRace', RacerData.PlayerData.source,
 | 
						|
                                    Races[RaceId])
 | 
						|
                            end
 | 
						|
                        end
 | 
						|
                        table.remove(AvailableRaces, AvailableKey)
 | 
						|
                        Races[RaceId].LastLeaderboard = {}
 | 
						|
                        Races[RaceId].Racers = {}
 | 
						|
                        Races[RaceId].Started = false
 | 
						|
                        Races[RaceId].Waiting = false
 | 
						|
                        LastRaces[RaceId] = nil
 | 
						|
                        TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
                    end
 | 
						|
                end)
 | 
						|
            else
 | 
						|
                TriggerClientEvent('QBCore:Notify', source, 'The race is already running', 'error')
 | 
						|
            end
 | 
						|
        else
 | 
						|
            TriggerClientEvent('QBCore:Notify', source, 'The race is already running', 'error')
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', source, 'This race does not exist :(', 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:CancelRace', function(raceId)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    local AvailableKey = GetOpenedRaceKey(raceId)
 | 
						|
 | 
						|
    TriggerClientEvent('QBCore:Notify', src, 'Stopping the race: ' .. raceId, 'error')
 | 
						|
 | 
						|
    if AvailableKey ~= nil then
 | 
						|
        if AvailableRaces[AvailableKey].SetupCitizenId == Player.PlayerData.citizenid then
 | 
						|
            for cid, _ in pairs(Races[raceId].Racers) do
 | 
						|
                local RacerData = QBCore.Functions.GetPlayerByCitizenId(cid)
 | 
						|
                if RacerData ~= nil then
 | 
						|
                    TriggerClientEvent('qb-lapraces:client:LeaveRace', RacerData.PlayerData.source, Races[raceId])
 | 
						|
                end
 | 
						|
            end
 | 
						|
 | 
						|
            table.remove(AvailableRaces, AvailableKey)
 | 
						|
            Races[raceId].LastLeaderboard = {}
 | 
						|
            Races[raceId].Racers = {}
 | 
						|
            Races[raceId].Started = false
 | 
						|
            Races[raceId].Waiting = false
 | 
						|
            LastRaces[raceId] = nil
 | 
						|
            TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', src, 'Race not open: ' .. raceId, 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:UpdateRaceState', function(RaceId, Started, Waiting)
 | 
						|
    Races[RaceId].Waiting = Waiting
 | 
						|
    Races[RaceId].Started = Started
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:UpdateRacerData', function(RaceId, Checkpoint, Lap, Finished)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local CitizenId = Player.PlayerData.citizenid
 | 
						|
 | 
						|
    Races[RaceId].Racers[CitizenId].Checkpoint = Checkpoint
 | 
						|
    Races[RaceId].Racers[CitizenId].Lap = Lap
 | 
						|
    Races[RaceId].Racers[CitizenId].Finished = Finished
 | 
						|
 | 
						|
    TriggerClientEvent('qb-lapraces:client:UpdateRaceRacerData', -1, RaceId, Races[RaceId])
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:StartRace', function(RaceId)
 | 
						|
    local src = source
 | 
						|
    local MyPlayer = QBCore.Functions.GetPlayer(src)
 | 
						|
    local AvailableKey = GetOpenedRaceKey(RaceId)
 | 
						|
 | 
						|
    if RaceId ~= nil then
 | 
						|
        if AvailableRaces[AvailableKey].SetupCitizenId == MyPlayer.PlayerData.citizenid then
 | 
						|
            AvailableRaces[AvailableKey].RaceData.Started = true
 | 
						|
            AvailableRaces[AvailableKey].RaceData.Waiting = false
 | 
						|
            for CitizenId, _ in pairs(Races[RaceId].Racers) do
 | 
						|
                local Player = QBCore.Functions.GetPlayerByCitizenId(CitizenId)
 | 
						|
                if Player ~= nil then
 | 
						|
                    TriggerClientEvent('qb-lapraces:client:RaceCountdown', Player.PlayerData.source)
 | 
						|
                end
 | 
						|
            end
 | 
						|
            TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
        else
 | 
						|
            TriggerClientEvent('QBCore:Notify', src, 'You are not the creator of the race..', 'error')
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', src, 'You are not in a race..', 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('qb-lapraces:server:SaveRace', function(RaceData)
 | 
						|
    local src = source
 | 
						|
    local Player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local RaceId = GenerateRaceId()
 | 
						|
    local Checkpoints = {}
 | 
						|
    for k, v in pairs(RaceData.Checkpoints) do
 | 
						|
        Checkpoints[k] = {
 | 
						|
            offset = v.offset,
 | 
						|
            coords = v.coords
 | 
						|
        }
 | 
						|
    end
 | 
						|
    Races[RaceId] = {
 | 
						|
        RaceName = RaceData.RaceName,
 | 
						|
        Checkpoints = Checkpoints,
 | 
						|
        Records = {},
 | 
						|
        Creator = Player.PlayerData.citizenid,
 | 
						|
        RaceId = RaceId,
 | 
						|
        Started = false,
 | 
						|
        Waiting = false,
 | 
						|
        Distance = math.ceil(RaceData.RaceDistance),
 | 
						|
        Racers = {},
 | 
						|
        LastLeaderboard = {}
 | 
						|
    }
 | 
						|
    MySQL.insert('INSERT INTO lapraces (name, checkpoints, creator, distance, raceid) VALUES (?, ?, ?, ?, ?)',
 | 
						|
        {RaceData.RaceName, json.encode(Checkpoints), Player.PlayerData.citizenid, RaceData.RaceDistance,
 | 
						|
         GenerateRaceId()})
 | 
						|
end)
 | 
						|
 | 
						|
-- Callbacks
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:GetRacingLeaderboards', function(_, cb)
 | 
						|
    cb(Races)
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:GetRaces', function(_, cb)
 | 
						|
    cb(AvailableRaces)
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:GetListedRaces', function(_, cb)
 | 
						|
    cb(Races)
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:GetRacingData', function(_, cb, RaceId)
 | 
						|
    cb(Races[RaceId])
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:HasCreatedRace', function(source, cb)
 | 
						|
    cb(HasOpenedRace(QBCore.Functions.GetPlayer(source).PlayerData.citizenid))
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:IsAuthorizedToCreateRaces', function(source, cb, TrackName)
 | 
						|
    cb(IsWhitelisted(QBCore.Functions.GetPlayer(source).PlayerData.citizenid), IsNameAvailable(TrackName))
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:CanRaceSetup', function(_, cb)
 | 
						|
    cb(Config.RaceSetupAllowed)
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Functions.CreateCallback('qb-lapraces:server:GetTrackData', function(_, cb, RaceId)
 | 
						|
    local result = MySQL.query.await('SELECT * FROM players WHERE citizenid = ?', {Races[RaceId].Creator})
 | 
						|
    if result[1] ~= nil then
 | 
						|
        result[1].charinfo = json.decode(result[1].charinfo)
 | 
						|
        cb(Races[RaceId], result[1])
 | 
						|
    else
 | 
						|
        cb(Races[RaceId], {
 | 
						|
            charinfo = {
 | 
						|
                firstname = "Unknown",
 | 
						|
                lastname = "Unknown"
 | 
						|
            }
 | 
						|
        })
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Commands
 | 
						|
 | 
						|
QBCore.Commands.Add("cancelrace", "Cancel going race..", {}, false, function(source, args)
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
 | 
						|
    if IsWhitelisted(Player.PlayerData.citizenid) then
 | 
						|
        local RaceName = table.concat(args, " ")
 | 
						|
        if RaceName ~= nil then
 | 
						|
            local RaceId = GetRaceId(RaceName)
 | 
						|
            if Races[RaceId].Started then
 | 
						|
                local AvailableKey = GetOpenedRaceKey(RaceId)
 | 
						|
                for cid, _ in pairs(Races[RaceId].Racers) do
 | 
						|
                    local RacerData = QBCore.Functions.GetPlayerByCitizenId(cid)
 | 
						|
                    if RacerData ~= nil then
 | 
						|
                        TriggerClientEvent('qb-lapraces:client:LeaveRace', RacerData.PlayerData.source, Races[RaceId])
 | 
						|
                    end
 | 
						|
                end
 | 
						|
                table.remove(AvailableRaces, AvailableKey)
 | 
						|
                Races[RaceId].LastLeaderboard = {}
 | 
						|
                Races[RaceId].Racers = {}
 | 
						|
                Races[RaceId].Started = false
 | 
						|
                Races[RaceId].Waiting = false
 | 
						|
                LastRaces[RaceId] = nil
 | 
						|
                TriggerClientEvent('qb-phone:client:UpdateLapraces', -1)
 | 
						|
            else
 | 
						|
                TriggerClientEvent('QBCore:Notify', source, 'This race has not started yet.', 'error')
 | 
						|
            end
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', source, 'You have not been authorized to do this.', 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
QBCore.Commands.Add("togglesetup", "Turn on / off racing setup", {}, false, function(source, _)
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
 | 
						|
    if IsWhitelisted(Player.PlayerData.citizenid) then
 | 
						|
        Config.RaceSetupAllowed = not Config.RaceSetupAllowed
 | 
						|
        if not Config.RaceSetupAllowed then
 | 
						|
            TriggerClientEvent('QBCore:Notify', source, 'No more races can be created!', 'error')
 | 
						|
        else
 | 
						|
            TriggerClientEvent('QBCore:Notify', source, 'Races can be created again!', 'success')
 | 
						|
        end
 | 
						|
    else
 | 
						|
        TriggerClientEvent('QBCore:Notify', source, 'You have not been authorized to do this.', 'error')
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Threads
 | 
						|
 | 
						|
CreateThread(function()
 | 
						|
    local races = MySQL.query.await('SELECT * FROM lapraces', {})
 | 
						|
    if races[1] ~= nil then
 | 
						|
        for _, v in pairs(races) do
 | 
						|
            local Records = {}
 | 
						|
            if v.records ~= nil then
 | 
						|
                Records = json.decode(v.records)
 | 
						|
            end
 | 
						|
            Races[v.raceid] = {
 | 
						|
                RaceName = v.name,
 | 
						|
                Checkpoints = json.decode(v.checkpoints),
 | 
						|
                Records = Records,
 | 
						|
                Creator = v.creator,
 | 
						|
                RaceId = v.raceid,
 | 
						|
                Started = false,
 | 
						|
                Waiting = false,
 | 
						|
                Distance = v.distance,
 | 
						|
                LastLeaderboard = {},
 | 
						|
                Racers = {}
 | 
						|
            }
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 |