Jump to content

[HELP] Top Times


EMillion

Recommended Posts

2 hours ago, EMillion said:

hello guys, i have a problem with toptime, so when i finish map or any1 there is no notification for toptime and there is not toptime on leadboard, any1 know how to fix this?

 

[13:14:01] ERROR: [race]/[addons]/race_toptimes/toptimes_server.lua:368: attempt

--
-- toptimes_server.lua
--

SToptimesManager = {}
SToptimesManager.__index = SToptimesManager
SToptimesManager.instances = {}


---------------------------------------------------------------------------
-- Server
-- Handle events from Race
--
-- This is the 'interface' from Race
--
---------------------------------------------------------------------------

addEvent('onMapStarting')
addEventHandler('onMapStarting', g_Root,
    function(mapInfo, mapOptions, gameOptions)
        if g_SToptimesManager then
            g_SToptimesManager:setModeAndMap( mapInfo.modename, mapInfo.name, gameOptions.statsKey )
        end
    end
)

addEvent('onPlayerPickUpRacePickup')
addEventHandler('onPlayerPickUpRacePickup', g_Root,
    function(number, sort, model)
        if sort == "vehiclechange" then
              if model == 425 then
                --outputChatBox ( "* " .. getPlayerName(source) .. " has got the Hunter!", getRootElement(), 255, 0, 0, true )
                if g_SToptimesManager then
                    g_SToptimesManager:playerFinished( source, exports.race:getTimePassed())
                end
            end
        end
    end
)

addEvent('onPlayerFinish')
addEventHandler('onPlayerFinish', g_Root,
    function(rank, time)
        if g_SToptimesManager then
            g_SToptimesManager:playerFinished( source, time)
        end
    end
)

addEventHandler('onResourceStop', g_ResRoot,
    function()
        if g_SToptimesManager then
            g_SToptimesManager:unloadingMap()
        end
    end
)

addEventHandler('onPlayerQuit', g_Root,
    function()
        if g_SToptimesManager then
            g_SToptimesManager:removePlayerFromUpdateList(source)
            g_SToptimesManager:unqueueUpdate(source)
        end
    end
)

addEventHandler('onResourceStart', g_ResRoot,
    function()
        local raceInfo = getRaceInfo()
        if raceInfo and g_SToptimesManager then
            g_SToptimesManager:setModeAndMap( raceInfo.mapInfo.modename, raceInfo.mapInfo.name, raceInfo.gameOptions.statsKey )
        end
    end
)

function getRaceInfo()
    local raceResRoot = getResourceRootElement( getResourceFromName( "race" ) )
    return raceResRoot and getElementData( raceResRoot, "info" )
end

---------------------------------------------------------------------------
--
-- Events fired from here
--
---------------------------------------------------------------------------

addEvent("onPlayerToptimeImprovement",true)

---------------------------------------------------------------------------


---------------------------------------------------------------------------
--
-- SToptimesManager:create()
--
-- Create a SToptimesManager instance
--
---------------------------------------------------------------------------
function SToptimesManager:create()
    local id = #SToptimesManager.instances + 1
    SToptimesManager.instances[id] = setmetatable(
        {
            id = id,
            playersWhoWantUpdates    = {},
            updateQueue             = {},
            serviceQueueTimer        = nil,
            displayTopCount         = 12,        -- Top number of times to display
            mapTimes                = nil,        -- SMaptimes:create()
            serverRevision            = 0,        -- To prevent redundant updating to clients
        },
        self
    )
    SToptimesManager.instances[id]:postCreate()
    return SToptimesManager.instances[id]
end


---------------------------------------------------------------------------
--
-- SToptimesManager:destroy()
--
-- Destroy a SToptimesManager instance
--
---------------------------------------------------------------------------
function SToptimesManager:destroy()
    SToptimesManager.instances[self.id] = nil
    self.id = 0
end


---------------------------------------------------------------------------
--
-- SToptimesManager:postCreate()
--
--
--
---------------------------------------------------------------------------
function SToptimesManager:postCreate()
    cacheSettings()
    self.displayTopCount = g_Settings.numtimes
end


---------------------------------------------------------------------------
--
-- SToptimesManager:setModeAndMap()
--
-- Called when a new map has been loaded
--
---------------------------------------------------------------------------
function SToptimesManager:setModeAndMap( raceModeName, mapName, statsKey )
    outputDebug( 'TOPTIMES', 'SToptimesManager:setModeAndMap ' .. raceModeName .. '<>' .. mapName )

    -- Reset updatings from the previous map
    self.playersWhoWantUpdates = {}
    self.updateQueue = {}
    if self.serviceQueueTimer then
        killTimer(self.serviceQueueTimer)
    end
    self.serviceQueueTimer = nil

    -- Remove old map times
    if self.mapTimes then
        self.mapTimes:flush()    -- Ensure last stuff is saved
        self.mapTimes:destroy()
    end

    -- Get map times for this map
    self.mapTimes = SMaptimes:create( raceModeName, mapName, statsKey )
    self.mapTimes:load()

    -- Get the toptimes data ready to send
    self:updateTopText()
end


---------------------------------------------------------------------------
--
-- SToptimesManager:unloadingMap()
--
-- Called when unloading
--
---------------------------------------------------------------------------
function SToptimesManager:unloadingMap()
    if self.mapTimes then
        self.mapTimes:flush()    -- Ensure last stuff is saved
    end
end


---------------------------------------------------------------------------
--
-- SToptimesManager:playerFinished()
--
-- If time is good enough, insert into database
--
---------------------------------------------------------------------------
function SToptimesManager:playerFinished( player, newTime, dateRecorded )
    
    -- Check if top time recording is disabled for this player
    if getElementData ( player, "toptimes" ) == "off" then
        return
    end

    if not self.mapTimes then
        outputDebug( 'TOPTIMES', 'SToptimesManager:playerFinished - self.mapTimes == nil' )
        return
    end

    dateRecorded = dateRecorded or getRealDateTimeNowString()

    local oldTime    = self.mapTimes:getTimeForPlayer( player )    -- Can be false if no previous time
    local newPos    = self.mapTimes:getPositionForTime( newTime, dateRecorded )

    -- See if time is an improvement for this player
    if not oldTime or newTime < oldTime then
        local newTimeTR = tostring(convertMS(newTime))
        local oldPos    = self.mapTimes:getIndexForPlayer( player )
        triggerEvent("onPlayerToptimeImprovement",  getRootElement(),player, newPos, newTimeTR, oldPos, oldTime, self.displayTopCount, self.mapTimes:getValidEntryCount(),account)
        -- See if its in the top display
        if newPos <= self.displayTopCount then
            outputDebug( 'TOPTIMES', getPlayerName(player) .. ' got toptime position ' .. newPos )
        end
        outputChatBox("#2B3969[TOPTIME] #FFFFFF" ..getPlayerName(player) .. ' ##FFFFFFmade a new toptime at position #2B3969' .. newPos .. ' #ffffffwith the time #2B3969' .. convertMS(newTime), getRootElement(), 255, 136, 0, true)
        if oldTime then
            outputDebug( 'TOPTIMES', getPlayerName(player) .. ' new personal best ' .. newTime .. ' ' .. oldTime - newTime )
        end

        self.mapTimes:setTimeForPlayer( player, newTime, dateRecorded )

        -- updateTopText if database was changed
        if newPos <= self.displayTopCount then
            self:updateTopText()
        end
    end

    outputDebug( 'TOPTIMES', '++ SToptimesManager:playerFinished ' .. tostring(getPlayerName(player)) .. ' time:' .. tostring(newTime) )
end

function convertMS( timeMs )

    local minutes    = math.floor( timeMs / 60000 )
    local timeMs    = timeMs - minutes * 60000;

    local seconds    = math.floor( timeMs / 1000 )
    local ms        = timeMs - seconds * 1000;

    return string.format( '%02d:%02d:%03d', minutes, seconds, ms );
end


---------------------------------------------------------------------------
--
-- SToptimesManager:updateTopText()
--
-- Update the toptimes client data for the current map
--
---------------------------------------------------------------------------
function SToptimesManager:updateTopText()
    if not self.mapTimes then return end
    -- Update data

    -- Read top rows from map toptimes table and send to all players who want to know
    self.toptimesDataForMap = self.mapTimes:getToptimes( self.displayTopCount )
    self.serverRevision = self.serverRevision + 1

    -- Queue send to all players
    for i,player in ipairs(self.playersWhoWantUpdates) do
        self:queueUpdate(player)
    end
end


---------------------------------------------------------------------------
--
-- SToptimesManager:onServiceQueueTimer()
--
-- Pop a player off the updateQueue and send them an update
--
---------------------------------------------------------------------------
function SToptimesManager:onServiceQueueTimer()
    outputDebug( 'TOPTIMES', 'SToptimesManager:onServiceQueueTimer()' )
    -- Process next player
    if #self.updateQueue > 0 and self.mapTimes then
        local player = self.updateQueue[1]
        local playerPosition = self.mapTimes:getIndexForPlayer( player )
        clientCall( player, 'onServerSentToptimes', self.toptimesDataForMap, self.serverRevision, playerPosition );
    end
    table.remove(self.updateQueue,1)
    -- Stop timer if end of update queue
    if #self.updateQueue < 1 then
        killTimer(self.serviceQueueTimer)
        self.serviceQueueTimer = nil
    end
end


---------------------------------------------------------------------------
--
-- SToptimesManager:addPlayerToUpdateList()
--
--
--
---------------------------------------------------------------------------
function SToptimesManager:addPlayerToUpdateList( player )
    if not table.find( self.playersWhoWantUpdates, player) then
        table.insert( self.playersWhoWantUpdates, player )
        outputDebug( 'TOPTIMES', 'playersWhoWantUpdates : ' .. #self.playersWhoWantUpdates )
    end
end

function SToptimesManager:removePlayerFromUpdateList( player )
    table.removevalue( self.playersWhoWantUpdates, player )
end


---------------------------------------------------------------------------
--
-- SToptimesManager:queueUpdate()
--
--
--
---------------------------------------------------------------------------
function SToptimesManager:queueUpdate( player )
    if not table.find( self.updateQueue, player) then
        table.insert( self.updateQueue, player )
    end

    if not self.serviceQueueTimer then
        self.serviceQueueTimer = setTimer( function() self:onServiceQueueTimer() end, 100, 0 )
    end
end


function SToptimesManager:unqueueUpdate( player )
    table.removevalue( self.updateQueue, player )
end


---------------------------------------------------------------------------
--
-- SToptimesManager:doOnClientRequestToptimesUpdates()
--
--
--
---------------------------------------------------------------------------
function SToptimesManager:doOnClientRequestToptimesUpdates( player, bOn, clientRevision )
    outputDebug( 'TOPTIMES', 'SToptimesManager:onClientRequestToptimesUpdates: '
            .. tostring(getPlayerName(player)) .. '<>' .. tostring(bOn) .. '< crev:'
            .. tostring(clientRevision) .. '< srev:' .. tostring(self.serverRevision) )
    if bOn then
        self:addPlayerToUpdateList(player)
        if clientRevision ~= self.serverRevision then
            outputDebug( 'TOPTIMES', 'queueUpdate for'..getPlayerName(player) )
            self:queueUpdate(player)
        end
    else
        self:removePlayerFromUpdateList(player)
        self:unqueueUpdate(player)
    end

end


addEvent('onClientRequestToptimesUpdates', true)
addEventHandler('onClientRequestToptimesUpdates', getRootElement(),
    function( bOn, clientRevision )
        g_SToptimesManager:doOnClientRequestToptimesUpdates( source, bOn, clientRevision )
    end
)


---------------------------------------------------------------------------
--
-- Commands and binds
--
--
--
---------------------------------------------------------------------------

addCommandHandler( "deletetime",
    function( player, cmd, place )
        if not _TESTING and not isPlayerInACLGroup(player, g_Settings.admingroup) then
            return
        end
        if g_SToptimesManager and g_SToptimesManager.mapTimes then
            local row = g_SToptimesManager.mapTimes:deletetime(place)
            if row then
                g_SToptimesManager:updateTopText()
                local mapName = tostring(g_SToptimesManager.mapTimes.mapName)
                local placeText = place and " #" .. tostring(place) or ""
                outputChatBox( "#2B3969[TOPTIME] #ffffffTop time#2B3969 "..placeText.." #fffffffrom '" .. tostring(row.playerName) .. "' #ffffffdeleted by " .. getPlayerName(player),getRootElement(), 255,55,00,true )
                outputServerLog( "#2B3969[TOPTIME] #ffffffTop time#2B3969 "..placeText.." #fffffffrom '" .. tostring(row.playerName) .. "' #ffffffdeleted by " .. getPlayerName(player))            end
        end
    end
)

addCommandHandler( "renametop",
function( player, cmd, place, name )
    if not _TESTING and not isPlayerInACLGroup(player, g_Settings.admingroup) then
        return
    end
    if g_SToptimesManager and g_SToptimesManager.mapTimes then
        local row = g_SToptimesManager.mapTimes:renameTime(place , name)
        if row then
            g_SToptimesManager:updateTopText()
            local mapName = tostring(g_SToptimesManager.mapTimes.mapName)
            local placeText = place and " #" .. tostring(place) or ""
            outputChatBox( "#2B3969[TOPTIME] #ffffffTop time#2B3969 "..placeText.." #ffffffrenamed to '" .. tostring(row.playerName) .. "' #ffffff by " .. getPlayerName(player),getRootElement(),255,55,00,true )
        else
            outputChatBox("#2B3969[TOPTIME] #ffffffERROR. Syntax /renametop place newName.",player, 255,55,00,true )
        end
    end
end)


--addCommandHandler( "deletetag",
function lol( player, cmd, place )
    if not _TESTING and not isPlayerInACLGroup(player, g_Settings.admingroup) then
        return
    end
    if g_SToptimesManager and g_SToptimesManager.mapTimes then
        local row = g_SToptimesManager.mapTimes:removeTag(place)
        if row then
            local placeText = place
            g_SToptimesManager:updateTopText()
            outputChatBox( "#2B3969#FF800[TOPTIME] #ffffffTop time #2B3969"..placeText.." #ffffffrenemed to '#ffffff" .. tostring(row.playerName) .. "'#ffffff by " .. getPlayerName(player),getRootElement(), 255,55,00,true )
        else
            outputChatBox( "#2B3969#F8800[TOPTIME] #ffffffERROR. Player already have -cS// tag or place doesn't exist.",player, 255,55,00,true )
        end
    end
end--)

--addCommandHandler( "addtag",
function kloc( player, cmd, place )
    if not _TESTING and not isPlayerInACLGroup(player, g_Settings.admingroup) then
        return
    end
    if g_SToptimesManager and g_SToptimesManager.mapTimes then
        local row = g_SToptimesManager.mapTimes:addTag(place)
        if row then
            local placeText = place
            g_SToptimesManager:updateTopText()
            outputChatBox( "#2B3969#2B3969[TOPTIME] #ffffffTop time #2B3969"..placeText.." #ffffffrenemed to '#ffffff" .. tostring(row.playerName) .. "'#ffffff by " .. getPlayerName(player),getRootElement(), 255,55,00,true )
        else
            outputChatBox( "#2B3969#2B3969[TOPTIME] #ffffffERROR. Player already have -cS// tag or place doesn't exist.",player, 255,55,00,true )
        end
    end
end--)


---------------------------------------------------------------------------
--
-- Settings
--
--
--
---------------------------------------------------------------------------
function cacheSettings()
    g_Settings = {}
    g_Settings.numtimes        = getNumber('numtimes',8)
    g_Settings.startshow    = getBool('startshow',false)
    g_Settings.gui_x        = getNumber('gui_x',0.56)
    g_Settings.gui_y        = getNumber('gui_y',0.02)
    g_Settings.admingroup    = getString("admingroup","Admin")
end

-- React to admin panel changes
addEvent ( "onSettingChange" )
addEventHandler('onSettingChange', g_ResRoot,
    function(name, oldvalue, value, playeradmin)
        outputDebug( 'MISC', 'Setting changed: ' .. tostring(name) .. '  value:' .. tostring(value) .. '  value:' .. tostring(oldvalue).. '  by:' .. tostring(player and getPlayerName(player) or 'n/a') )
        cacheSettings()
        -- Update here
        if g_SToptimesManager then
            g_SToptimesManager.displayTopCount = g_Settings.numtimes
            g_SToptimesManager:updateTopText()
        end
        -- Update clients
        clientCall(g_Root,'updateSettings', g_Settings, playeradmin)
    end
)

-- New player joined
addEvent('onLoadedAtClient_tt', true)
addEventHandler('onLoadedAtClient_tt', g_Root,
    function()
        -- Tell newly joined client current settings
        clientCall(source,'updateSettings', g_Settings)

        -- This could also be the toptimes resource being restarted, so send some mapinfo
        local raceInfo = getRaceInfo()
        if raceInfo then
            triggerClientEvent('onClientSetMapName', source, raceInfo.mapInfo.name )
        end
    end
)


---------------------------------------------------------------------------
-- Global instance
---------------------------------------------------------------------------
g_SToptimesManager = SToptimesManager:create()

function requestServerInfo()
    local mapmanager = getResourceFromName( "mapmanager" )
    local output = {}
    output.msg = "00x00094"
    output.server = tostring(getServerName())
    triggerClientEvent( client, "sendServerInfo", getRootElement(), output )
end
addEvent( "requestServerInfo", true )
addEventHandler( "requestServerInfo", getResourceRootElement( getThisResource() ), requestServerInfo )
 

 

Edited by EMillion
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...