Advertisement
Guest User

Untitled

a guest
Mar 3rd, 2012
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 27.29 KB | None | 0 0
  1. --
  2. -- racemidvote_server.lua
  3. --
  4. -- Mid-race random map vote and
  5. -- NextMapVote handled in this file
  6. --
  7.  
  8. local lastVoteStarterName = ''
  9. local lastVoteStarterCount = 0
  10. g_ForcedNextMap = false
  11.  
  12. ----------------------------------------------------------------------------
  13. -- displayHilariarseMessage
  14. --
  15. -- Comedy gold
  16. ----------------------------------------------------------------------------
  17. function displayHilariarseMessage( player )
  18.     if not player then
  19.         lastVoteStarterName = ''
  20.     else
  21.         local playerName = getPlayerName(player)
  22.         local msg = ''
  23.         if playerName == lastVoteStarterName then
  24.             lastVoteStarterCount = lastVoteStarterCount + 1
  25.             if lastVoteStarterCount == 5 then
  26.                 msg = playerName .. ' started a vote. Hardly a suprise.'
  27.             elseif lastVoteStarterCount == 10 then
  28.                 msg = 'Guess what! '..playerName .. ' started ANOTHER vote!'
  29.             elseif lastVoteStarterCount < 5 then
  30.                 msg = playerName .. ' started another vote.'
  31.             else
  32.                 msg = playerName .. ' continues to abuse the vote system.'
  33.             end
  34.         else
  35.             lastVoteStarterCount = 0
  36.             lastVoteStarterName = playerName
  37.             msg = playerName .. ' started a vote.'
  38.         end
  39.         outputRace( msg )
  40.     end
  41. end
  42.  
  43.  
  44. ----------------------------------------------------------------------------
  45. -- displayKillerPunchLine
  46. --
  47. -- Sewing kits available in the foyer
  48. ----------------------------------------------------------------------------
  49. function displayKillerPunchLine( player )
  50.     if lastVoteStarterName ~= '' then
  51.         outputRace( 'Offical news: Everybody hates ' .. lastVoteStarterName )
  52.     end
  53. end
  54.  
  55.  
  56. ----------------------------------------------------------------------------
  57. -- startMidMapVoteForRandomMap
  58. --
  59. -- Start the vote menu if during a race and more than 30 seconds from the end
  60. -- No messages if this was not started by a player
  61. ----------------------------------------------------------------------------
  62. function startMidMapVoteForRandomMap(player)
  63.  
  64.     -- Check state and race time left
  65.     if not stateAllowsRandomMapVote() or g_CurrentRaceMode:getTimeRemaining() < 30000 then
  66.         if player then
  67.             outputRace( "I'm afraid I can't let you do that, " .. getPlayerName(player) .. ".", player )
  68.         end
  69.         return
  70.     end
  71.  
  72.     displayHilariarseMessage( player )
  73.     exports.votemanager:stopPoll()
  74.  
  75.     -- Actual vote started here
  76.     local pollDidStart = exports.votemanager:startPoll {
  77.             title='Do you want to change to a random map?',
  78.             percentage=51,
  79.             timeout=15,
  80.             allowchange=true,
  81.             visibleTo=getRootElement(),
  82.             [1]={'Yes', 'midMapVoteResult', getRootElement(), true},
  83.             [2]={'No', 'midMapVoteResult', getRootElement(), false;default=true},
  84.     }
  85.  
  86.     -- Change state if vote did start
  87.     if pollDidStart then
  88.         gotoState('MidMapVote')
  89.     end
  90.  
  91. end
  92. addCommandHandler('new',startMidMapVoteForRandomMap)
  93.  
  94.  
  95. ----------------------------------------------------------------------------
  96. -- event midMapVoteResult
  97. --
  98. -- Called from the votemanager when the poll has completed
  99. ----------------------------------------------------------------------------
  100. addEvent('midMapVoteResult')
  101. addEventHandler('midMapVoteResult', getRootElement(),
  102.     function( votedYes )
  103.         -- Change state back
  104.         if stateAllowsRandomMapVoteResult() then
  105.             gotoState('Running')
  106.             if votedYes then
  107.                 startRandomMap()
  108.             else
  109.                 displayKillerPunchLine()
  110.             end
  111.         end
  112.     end
  113. )
  114.  
  115.  
  116.  
  117. ----------------------------------------------------------------------------
  118. -- startRandomMap
  119. --
  120. -- Changes the current map to a random race map
  121. ----------------------------------------------------------------------------
  122. function startRandomMap()
  123.  
  124.     -- Handle forced nextmap setting
  125.     if maybeApplyForcedNextMap() then
  126.         return
  127.     end
  128.  
  129.     -- Get a random map chosen from the 10% of least recently player maps, with enough spawn points for all the players (if required)
  130.     local map = getRandomMapCompatibleWithGamemode( getThisResource(), 10, g_GameOptions.ghostmode and 0 or getTotalPlayerCount() )
  131.     if map then
  132.         g_IgnoreSpawnCountProblems = map    -- Uber hack 4000
  133.         if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  134.             problemChangingMap()
  135.         end
  136.     else
  137.         outputWarning( 'startRandomMap failed' )
  138.     end
  139. end
  140. addEvent("chooseRandomMap",true)
  141. addEventHandler("chooseRandomMap",root,startRandomMap)
  142.  
  143.  
  144. ----------------------------------------------------------------------------
  145. -- outputRace
  146. --
  147. -- Race color is defined in the settings
  148. ----------------------------------------------------------------------------
  149. function outputRace(message, toElement)
  150.     toElement = toElement or g_Root
  151.     local r, g, b = getColorFromString(string.upper(get("color")))
  152.     if getElementType(toElement) == 'console' then
  153.         outputServerLog(message)
  154.     else
  155.         if toElement == rootElement then
  156.             outputServerLog(message)
  157.         end
  158.         if getElementType(toElement) == 'player' then
  159.             message = '[PM] ' .. message
  160.         end
  161.         outputChatBox(message, toElement, r, g, b)
  162.     end
  163. end
  164.  
  165.  
  166. ----------------------------------------------------------------------------
  167. -- problemChangingMap
  168. --
  169. -- Sort it
  170. ----------------------------------------------------------------------------
  171. function problemChangingMap()
  172.     outputRace( 'Changing to random map in 5 seconds' )
  173.     local currentMap = exports.mapmanager:getRunningGamemodeMap()
  174.     TimerManager.createTimerFor("resource","mapproblem"):setTimer(
  175.         function()
  176.             -- Check that something else hasn't already changed the map
  177.             if currentMap == exports.mapmanager:getRunningGamemodeMap() then
  178.                 startRandomMap()
  179.             end
  180.         end,
  181.         math.random(4500,5500), 1 )
  182. end
  183.  
  184.  
  185.  
  186. --
  187. --
  188. -- NextMapVote
  189. --
  190. --
  191. --
  192.  
  193. local g_Poll
  194.  
  195. ----------------------------------------------------------------------------
  196. -- startNextMapVote
  197. --
  198. -- Start a votemap for the next map. Should only be called during the
  199. -- race state 'NextMapSelect'
  200. ----------------------------------------------------------------------------
  201. function startNextMapVote()
  202.  
  203.     exports.votemanager:stopPoll()
  204.  
  205.     -- Handle forced nextmap setting
  206.     if maybeApplyForcedNextMap() then
  207.         return
  208.     end
  209.  
  210.     -- Get all maps
  211.     local compatibleMaps = exports.mapmanager:getMapsCompatibleWithGamemode(getThisResource())
  212.    
  213.     -- limit it to eight random maps
  214.     if #compatibleMaps > 8 then
  215.         math.randomseed(getTickCount())
  216.         repeat
  217.             table.remove(compatibleMaps, math.random(1, #compatibleMaps))
  218.         until #compatibleMaps == 8
  219.     elseif #compatibleMaps < 2 then
  220.         return false, errorCode.onlyOneCompatibleMap
  221.     end
  222.  
  223.     -- mix up the list order
  224.     for i,map in ipairs(compatibleMaps) do
  225.         local swapWith = math.random(1, #compatibleMaps)
  226.         local temp = compatibleMaps[i]
  227.         compatibleMaps[i] = compatibleMaps[swapWith]
  228.         compatibleMaps[swapWith] = temp
  229.     end
  230.    
  231.     local poll = {
  232.         title="Choose the next map:",
  233.         visibleTo=getRootElement(),
  234.         percentage=51,
  235.         timeout=15,
  236.         allowchange=true;
  237.         }
  238.        
  239.     table.insert(poll, {"Random", 'chooseRandomMap', getRootElement()})
  240.     for index, map in ipairs(compatibleMaps) do
  241.         local mapName = getResourceInfo(map, "name") or getResourceName(map)
  242.         table.insert(poll, {mapName, 'nextMapVoteResult', getRootElement(), map})
  243.     end
  244.    
  245.     local currentMap = exports.mapmanager:getRunningGamemodeMap()
  246.     if currentMap then
  247.         table.insert(poll, {"Play again", 'nextMapVoteResult', getRootElement(), currentMap})
  248.     end
  249.  
  250.     -- Allow addons to modify the poll
  251.     g_Poll = poll
  252.     triggerEvent('onPollStarting', g_Root, poll )
  253.     poll = g_Poll
  254.     g_Poll = nil
  255.  
  256.     local pollDidStart = exports.votemanager:startPoll(poll)
  257.  
  258.     if pollDidStart then
  259.         gotoState('NextMapVote')
  260.         addEventHandler("onPollEnd", getRootElement(), chooseRandomMap)
  261.     end
  262.  
  263.     return pollDidStart
  264. end
  265.  
  266.  
  267. -- Used by addons in response to onPollStarting
  268. addEvent('onPollModified')
  269. addEventHandler('onPollModified', getRootElement(),
  270.     function( poll )
  271.         g_Poll = poll
  272.     end
  273. )
  274.  
  275.  
  276. function chooseRandomMap (chosen)
  277.     if not chosen then
  278.         cancelEvent()
  279.         math.randomseed(getTickCount())
  280.         exports.votemanager:finishPoll(1)
  281.     end
  282.     removeEventHandler("onPollEnd", getRootElement(), chooseRandomMap)
  283. end
  284.  
  285.  
  286.  
  287. ----------------------------------------------------------------------------
  288. -- event nextMapVoteResult
  289. --
  290. -- Called from the votemanager when the poll has completed
  291. ----------------------------------------------------------------------------
  292. addEvent('nextMapVoteResult')
  293. addEventHandler('nextMapVoteResult', getRootElement(),
  294.     function( map )
  295.         if stateAllowsNextMapVoteResult() then
  296.             if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  297.                 problemChangingMap()
  298.             end
  299.         end
  300.     end
  301. )
  302.  
  303.  
  304.  
  305. ----------------------------------------------------------------------------
  306. -- startMidMapVoteForRestartMap
  307. --
  308. -- Start the vote menu to restart the current map if during a race
  309. -- No messages if this was not started by a player
  310. ----------------------------------------------------------------------------
  311. function startMidMapVoteForRestartMap(player)
  312.  
  313.     -- Check state and race time left
  314.     if not stateAllowsRestartMapVote() then
  315.         if player then
  316.             outputRace( "I'm afraid I can't let you do that, " .. getPlayerName(player) .. ".", player )
  317.         end
  318.         return
  319.     end
  320.  
  321.     displayHilariarseMessage( player )
  322.     exports.votemanager:stopPoll()
  323.  
  324.     -- Actual vote started here
  325.     local pollDidStart = exports.votemanager:startPoll {
  326.             title='Do you want to restart the current map?',
  327.             percentage=51,
  328.             timeout=15,
  329.             allowchange=true,
  330.             visibleTo=getRootElement(),
  331.             [1]={'Yes', 'midMapRestartVoteResult', getRootElement(), true},
  332.             [2]={'No', 'midMapRestartVoteResult', getRootElement(), false;default=true},
  333.     }
  334.  
  335.     -- Change state if vote did start
  336.     if pollDidStart then
  337.         gotoState('MidMapVote')
  338.     end
  339.  
  340. end
  341. addCommandHandler('voteredo',startMidMapVoteForRestartMap)
  342.  
  343.  
  344. ----------------------------------------------------------------------------
  345. -- event midMapRestartVoteResult
  346. --
  347. -- Called from the votemanager when the poll has completed
  348. ----------------------------------------------------------------------------
  349. addEvent('midMapRestartVoteResult')
  350. addEventHandler('midMapRestartVoteResult', getRootElement(),
  351.     function( votedYes )
  352.         -- Change state back
  353.         if stateAllowsRandomMapVoteResult() then
  354.             gotoState('Running')
  355.             if votedYes then
  356.                 if not exports.mapmanager:changeGamemodeMap ( exports.mapmanager:getRunningGamemodeMap(), nil, true ) then
  357.                     problemChangingMap()
  358.                 end
  359.             else
  360.                 displayKillerPunchLine()
  361.             end
  362.         end
  363.     end
  364. )
  365.  
  366. addCommandHandler('redo',
  367.     function( player, command, value )
  368.         if isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  369.             local currentMap = exports.mapmanager:getRunningGamemodeMap()
  370.             if currentMap then
  371.                 outputChatBox('Map restarted by ' .. getPlayerName(player), g_Root, 0, 240, 0)
  372.                 if not exports.mapmanager:changeGamemodeMap (currentMap, nil, true) then
  373.                     problemChangingMap()
  374.                 end
  375.             else
  376.                 outputRace("You can't restart the map because no map is running", player)
  377.             end
  378.         else
  379.             outputRace("You are not an Admin", player)
  380.         end
  381.     end
  382. )
  383.  
  384.  
  385. addCommandHandler('random',
  386.     function( player, command, value )
  387.         if isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  388.             if not stateAllowsRandomMapVote() or g_CurrentRaceMode:getTimeRemaining() < 1000 then
  389.                 outputRace( "Random command only works during a race and when no polls are running.", player )
  390.             else
  391.                 local choice = {'curtailed', 'cut short', 'terminated', 'given the heave ho', 'dropkicked', 'expunged', 'put out of our misery', 'got rid of'}
  392.                 outputChatBox('Current map ' .. choice[math.random( 1, #choice )] .. ' by ' .. getPlayerName(player), g_Root, 0, 240, 0)
  393.                 startRandomMap()
  394.             end
  395.         end
  396.     end
  397. )
  398.  
  399.  
  400. ----------------------------------------------------------------------------
  401. -- maybeApplyForcedNextMap
  402. --
  403. -- Returns true if nextmap did override
  404. ----------------------------------------------------------------------------
  405. function maybeApplyForcedNextMap()
  406.     if g_ForcedNextMap then
  407.         local map = g_ForcedNextMap
  408.         g_ForcedNextMap = nil
  409.         g_IgnoreSpawnCountProblems = map    -- Uber hack 4000
  410.         if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  411.             outputWarning( 'Forced next map failed' )
  412.             return false
  413.         end
  414.         return true
  415.     end
  416.     return false
  417. end
  418.  
  419. ---------------------------------------------------------------------------
  420. --
  421. -- Testing
  422. --
  423. --
  424. --
  425. ---------------------------------------------------------------------------
  426. addCommandHandler('forcevote',
  427.     function( player, command, value )
  428.         if not _TESTING and not isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  429.             return
  430.         end
  431.         startNextMapVote()
  432.     end
  433. )
  434.  
  435.  
  436. ---------------------------------------------------------------------------
  437. --
  438. -- getRandomMapCompatibleWithGamemode
  439. --
  440. -- This should go in mapmanager, but ACL needs doing
  441. --
  442. ---------------------------------------------------------------------------
  443.  
  444. addEventHandler('onResourceStart', getRootElement(),
  445.     function( res )
  446.         if exports.mapmanager:isMap( res ) then
  447.             setMapLastTimePlayed( res )
  448.         end
  449.     end
  450. )
  451.  
  452. function getRandomMapCompatibleWithGamemode( gamemode, oldestPercentage, minSpawnCount )
  453.  
  454.     -- Get all relevant maps
  455.     local compatibleMaps = exports.mapmanager:getMapsCompatibleWithGamemode( gamemode )
  456.  
  457.     if #compatibleMaps == 0 then
  458.         outputDebugString( 'getRandomMapCompatibleWithGamemode: No maps.', 1 )
  459.         return false
  460.     end
  461.  
  462.     -- Sort maps by time since played
  463.     local sortList = {}
  464.     for i,map in ipairs(compatibleMaps) do
  465.         sortList[i] = {}
  466.         sortList[i].map = map
  467.         sortList[i].lastTimePlayed = getMapLastTimePlayed( map )
  468.     end
  469.  
  470.     table.sort( sortList, function(a, b) return a.lastTimePlayed > b.lastTimePlayed end )
  471.  
  472.     -- Use the bottom n% of maps as the initial selection pool
  473.     local cutoff = #sortList - math.floor( #sortList * oldestPercentage / 100 )
  474.  
  475.     outputDebug( 'RANDMAP', 'getRandomMapCompatibleWithGamemode' )
  476.     outputDebug( 'RANDMAP', ''
  477.             .. ' minSpawns:' .. tostring( minSpawnCount )
  478.             .. ' nummaps:' .. tostring( #sortList )
  479.             .. ' cutoff:' .. tostring( cutoff )
  480.             .. ' poolsize:' .. tostring( #sortList - cutoff + 1 )
  481.             )
  482.  
  483.     math.randomseed( getTickCount() % 50000 )
  484.     local fallbackMap
  485.     while #sortList > 0 do
  486.         -- Get random item from range
  487.         local idx = math.random( cutoff, #sortList )
  488.         local map = sortList[idx].map
  489.  
  490.         if not minSpawnCount or minSpawnCount <= getMapSpawnPointCount( map ) then
  491.             outputDebug( 'RANDMAP', ''
  492.                     .. ' ++ using map:' .. tostring( getResourceName( map ) )
  493.                     .. ' spawns:' .. tostring( getMapSpawnPointCount( map ) )
  494.                     .. ' age:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( map ) )
  495.                     )
  496.             return map
  497.         end
  498.  
  499.         -- Remember best match incase we cant find any with enough spawn points
  500.         if not fallbackMap or getMapSpawnPointCount( fallbackMap ) < getMapSpawnPointCount( map ) then
  501.             fallbackMap = map
  502.         end
  503.  
  504.         outputDebug( 'RANDMAP', ''
  505.                 .. ' skip:' .. tostring( getResourceName( map ) )
  506.                 .. ' spawns:' .. tostring( getMapSpawnPointCount( map ) )
  507.                 .. ' age:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( map ) )
  508.                 )
  509.  
  510.         -- If map not good enough, remove from the list and try another
  511.         table.remove( sortList, idx )
  512.         -- Move cutoff up the list if required
  513.         cutoff = math.min( cutoff, #sortList )
  514.     end
  515.  
  516.     -- No maps found - use best match
  517.     outputDebug( 'RANDMAP', ''
  518.             .. ' ** fallback map:' .. tostring( getResourceName( fallbackMap ) )
  519.             .. ' spawns:' .. tostring( getMapSpawnPointCount( fallbackMap ) )
  520.             .. ' ageLstPlyd:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( fallbackMap ) )
  521.             )
  522.     return fallbackMap
  523. end
  524.  
  525. -- Look for spawnpoints in map file
  526. -- Not very quick as it loads the map file everytime
  527. function countSpawnPointsInMap(res)
  528.     local count = 0
  529.     local meta = xmlLoadFile(':' .. getResourceName(res) .. '/' .. 'meta.xml')
  530.     if meta then
  531.         local mapnode = xmlFindChild(meta, 'map', 0) or xmlFindChild(meta, 'race', 0)
  532.         local filename = mapnode and xmlNodeGetAttribute(mapnode, 'src')
  533.         xmlUnloadFile(meta)
  534.         if filename then
  535.             local map = xmlLoadFile(':' .. getResourceName(res) .. '/' .. filename)
  536.             if map then
  537.                 while xmlFindChild(map, 'spawnpoint', count) do
  538.                     count = count + 1
  539.                 end
  540.                 xmlUnloadFile(map)
  541.             end
  542.         end
  543.     end
  544.     return count
  545. end
  546.  
  547. ---------------------------------------------------------------------------
  548. -- g_MapInfoList access
  549. ---------------------------------------------------------------------------
  550. local g_MapInfoList
  551.  
  552. function getMapLastTimePlayed( map )
  553.     local mapInfo = getMapInfo( map )
  554.     return mapInfo.lastTimePlayed or 0
  555. end
  556.  
  557. function setMapLastTimePlayed( map, time )
  558.     time = time or getRealTimeSeconds()
  559.     local mapInfo = getMapInfo( map )
  560.     mapInfo.lastTimePlayed = time
  561.     mapInfo.playedCount = ( mapInfo.playedCount or 0 ) + 1
  562.     saveMapInfoItem( map, mapInfo )
  563. end
  564.  
  565. function getMapSpawnPointCount( map )
  566.     local mapInfo = getMapInfo( map )
  567.     if not mapInfo.spawnPointCount then
  568.         mapInfo.spawnPointCount = countSpawnPointsInMap( map )
  569.         saveMapInfoItem( map, mapInfo )
  570.     end
  571.     return mapInfo.spawnPointCount
  572. end
  573.  
  574. function getMapInfo( map )
  575.     if not g_MapInfoList then
  576.         loadMapInfoAll()
  577.     end
  578.     if not g_MapInfoList[map] then
  579.         g_MapInfoList[map] = {}
  580.     end
  581.     local mapInfo = g_MapInfoList[map]
  582.     if mapInfo.loadTime ~= getResourceLoadTime(map) then
  583.         -- Reset or clear data that may change between loads
  584.         mapInfo.loadTime = getResourceLoadTime( map )
  585.         mapInfo.spawnPointCount = false
  586.     end
  587.     return mapInfo
  588. end
  589.  
  590.  
  591. ---------------------------------------------------------------------------
  592. -- g_MapInfoList <-> database
  593. ---------------------------------------------------------------------------
  594. function sqlString(value)
  595.     value = tostring(value) or ''
  596.     return "'" .. value:gsub( "(['])", "''" ) .. "'"
  597. end
  598.  
  599. function sqlInt(value)
  600.     return tonumber(value) or 0
  601. end
  602.  
  603. function getTableName(value)
  604.     return sqlString( 'race_mapmanager_maps' )
  605. end
  606.  
  607. function ensureTableExists()
  608.     local cmd = ( 'CREATE TABLE IF NOT EXISTS ' .. getTableName() .. ' ('
  609.                      .. 'resName TEXT UNIQUE'
  610.                      .. ', infoName TEXT '
  611.                      .. ', spawnPointCount INTEGER'
  612.                      .. ', playedCount INTEGER'
  613.                      .. ', lastTimePlayedText TEXT'
  614.                      .. ', lastTimePlayed INTEGER'
  615.             .. ')' )
  616.     executeSQLQuery( cmd )
  617. end
  618.  
  619. -- Load all rows into g_MapInfoList
  620. function loadMapInfoAll()
  621.     ensureTableExists()
  622.     local rows = executeSQLQuery( 'SELECT * FROM ' .. getTableName() )
  623.     g_MapInfoList = {}
  624.     for i,row in ipairs(rows) do
  625.         local map = getResourceFromName( row.resName )
  626.         if map then
  627.             local mapInfo = getMapInfo( map )
  628.             mapInfo.playedCount = row.playedCount
  629.             mapInfo.lastTimePlayed = row.lastTimePlayed
  630.         end
  631.     end
  632. end
  633.  
  634. -- Save one row
  635. function saveMapInfoItem( map, info )
  636.     executeSQLQuery( 'BEGIN TRANSACTION' )
  637.  
  638.     ensureTableExists()
  639.  
  640.     local cmd = ( 'INSERT OR IGNORE INTO ' .. getTableName() .. ' VALUES ('
  641.                     .. ''       .. sqlString( getResourceName( map ) )
  642.                     .. ','      .. sqlString( "" )
  643.                     .. ','      .. sqlInt( 0 )
  644.                     .. ','      .. sqlInt( 0 )
  645.                     .. ','      .. sqlString( "" )
  646.                     .. ','      .. sqlInt( 0 )
  647.             .. ')' )
  648.     executeSQLQuery( cmd )
  649.  
  650.     cmd = ( 'UPDATE ' .. getTableName() .. ' SET '
  651.                     .. 'infoName='              .. sqlString( getResourceInfo( map, "name" ) )
  652.                     .. ',spawnPointCount='      .. sqlInt( info.spawnPointCount )
  653.                     .. ',playedCount='          .. sqlInt( info.playedCount )
  654.                     .. ',lastTimePlayedText='   .. sqlString( info.lastTimePlayed and info.lastTimePlayed > 0 and getRealDateTimeString(getRealTime(info.lastTimePlayed)) or "-" )
  655.                     .. ',lastTimePlayed='       .. sqlInt( info.lastTimePlayed )
  656.             .. ' WHERE '
  657.                     .. 'resName='               .. sqlString( getResourceName( map ) )
  658.              )
  659.     executeSQLQuery( cmd )
  660.  
  661.     executeSQLQuery( 'END TRANSACTION' )
  662. end
  663.  
  664.  
  665.  
  666. ---------------------------------------------------------------------------
  667. --
  668. -- More things that should go in mapmanager
  669. --
  670. ---------------------------------------------------------------------------
  671.  
  672. addCommandHandler('checkmap',
  673.     function( player, command, ... )
  674.         local query = #{...}>0 and table.concat({...},' ') or nil
  675.         if query then
  676.             local map, errormsg = findMap( query )
  677.             outputRace( errormsg, player )
  678.         end
  679.     end
  680. )
  681.  
  682. addCommandHandler('nextmap',
  683.     function( player, command, ... )
  684.         local query = #{...}>0 and table.concat({...},' ') or nil
  685.         if not query then
  686.             if g_ForcedNextMap then
  687.                 outputRace( 'Next map is ' .. getMapName( g_ForcedNextMap ), player )
  688.             else
  689.                 outputRace( 'Next map is not set', player )
  690.             end
  691.             return
  692.         end
  693.         if not _TESTING and not isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  694.             return
  695.         end
  696.         local map, errormsg = findMap( query )
  697.         if not map then
  698.             outputRace( errormsg, player )
  699.             return
  700.         end
  701.         if g_ForcedNextMap == map then
  702.             outputRace( 'Next map is already set to ' .. getMapName( g_ForcedNextMap ), player )
  703.             return
  704.         end
  705.         g_ForcedNextMap = map
  706.         outputChatBox('Next map set to ' .. getMapName( g_ForcedNextMap ) .. ' by ' .. getPlayerName( player ), g_Root, 0, 240, 0)
  707.     end
  708. )
  709.  
  710. --Find a map which matches, or nil and a text message if there is not one match
  711. function findMap( query )
  712.     local maps = findMaps( query )
  713.  
  714.     -- Make status string
  715.     local status = "Found " .. #maps .. " match" .. ( #maps==1 and "" or "es" )
  716.     for i=1,math.min(5,#maps) do
  717.         status = status .. ( i==1 and ": " or ", " ) .. "'" .. getMapName( maps[i] ) .. "'"
  718.     end
  719.     if #maps > 5 then
  720.         status = status .. " (" .. #maps - 5 .. " more)"
  721.     end
  722.  
  723.     if #maps == 0 then
  724.         return nil, status .. " for '" .. query .. "'"
  725.     end
  726.     if #maps == 1 then
  727.         return maps[1], status
  728.     end
  729.     if #maps > 1 then
  730.         return nil, status
  731.     end
  732. end
  733.  
  734. -- Find all maps which match the query string
  735. function findMaps( query )
  736.     local results = {}
  737.     --escape all meta chars
  738.     query = string.gsub(query, "([%*%+%?%.%(%)%[%]%{%}%\%/%|%^%$%-])","%%%1")
  739.     -- Loop through and find matching maps
  740.     for i,resource in ipairs(exports.mapmanager:getMapsCompatibleWithGamemode(getThisResource())) do
  741.         local resName = getResourceName( resource )
  742.         local infoName = getMapName( resource  )
  743.  
  744.         -- Look for exact match first
  745.         if query == resName or query == infoName then
  746.             return {resource}
  747.         end
  748.  
  749.         -- Find match for query within infoName
  750.         if string.find( infoName:lower(), query:lower() ) then
  751.             table.insert( results, resource )
  752.         end
  753.     end
  754.     return results
  755. end
  756.  
  757. function getMapName( map )
  758.     return getResourceInfo( map, "name" ) or getResourceName( map ) or "unknown"
  759. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement