mirror of
https://github.com/citizenfx/cfx-server-data.git
synced 2025-01-10 15:43:00 +08:00
308 lines
7.9 KiB
Lua
308 lines
7.9 KiB
Lua
-- loosely based on MTA's https://code.google.com/p/mtasa-resources/source/browse/trunk/%5Bmanagers%5D/mapmanager/mapmanager_main.lua
|
|
|
|
local maps = {}
|
|
local gametypes = {}
|
|
|
|
local function refreshResources()
|
|
local numResources = GetNumResources()
|
|
|
|
for i = 0, numResources - 1 do
|
|
local resource = GetResourceByFindIndex(i)
|
|
|
|
if GetNumResourceMetadata(resource, 'resource_type') > 0 then
|
|
local type = GetResourceMetadata(resource, 'resource_type', 0)
|
|
local params = json.decode(GetResourceMetadata(resource, 'resource_type_extra', 0))
|
|
|
|
if type == 'map' then
|
|
maps[resource] = params
|
|
elseif type == 'gametype' then
|
|
gametypes[resource] = params
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
AddEventHandler('onResourceListRefresh', function()
|
|
refreshResources()
|
|
end)
|
|
|
|
refreshResources()
|
|
|
|
AddEventHandler('onResourceStarting', function(resource)
|
|
local num = GetNumResourceMetadata(resource, 'map')
|
|
|
|
if num then
|
|
for i = 0, num-1 do
|
|
local file = GetResourceMetadata(resource, 'map', i)
|
|
|
|
if file then
|
|
addMap(file, resource)
|
|
end
|
|
end
|
|
end
|
|
|
|
if maps[resource] then
|
|
if getCurrentMap() and getCurrentMap() ~= resource then
|
|
if doesMapSupportGameType(getCurrentGameType(), resource) then
|
|
print("Changing map from " .. getCurrentMap() .. " to " .. resource)
|
|
|
|
changeMap(resource)
|
|
else
|
|
-- check if there's only one possible game type for the map
|
|
local map = maps[resource]
|
|
local count = 0
|
|
local gt
|
|
|
|
for type, flag in pairs(map.gameTypes) do
|
|
if flag then
|
|
count = count + 1
|
|
gt = type
|
|
end
|
|
end
|
|
|
|
if count == 1 then
|
|
print("Changing map from " .. getCurrentMap() .. " to " .. resource .. " (gt " .. gt .. ")")
|
|
|
|
changeGameType(gt)
|
|
changeMap(resource)
|
|
end
|
|
end
|
|
|
|
CancelEvent()
|
|
end
|
|
elseif gametypes[resource] then
|
|
if getCurrentGameType() and getCurrentGameType() ~= resource then
|
|
print("Changing gametype from " .. getCurrentGameType() .. " to " .. resource)
|
|
|
|
changeGameType(resource)
|
|
|
|
CancelEvent()
|
|
end
|
|
end
|
|
end)
|
|
|
|
math.randomseed(GetInstanceId())
|
|
|
|
local currentGameType = nil
|
|
local currentMap = nil
|
|
|
|
AddEventHandler('onResourceStart', function(resource)
|
|
if maps[resource] then
|
|
if not getCurrentGameType() then
|
|
for gt, _ in pairs(maps[resource].gameTypes) do
|
|
changeGameType(gt)
|
|
break
|
|
end
|
|
end
|
|
|
|
if getCurrentGameType() and not getCurrentMap() then
|
|
if doesMapSupportGameType(currentGameType, resource) then
|
|
if TriggerEvent('onMapStart', resource, maps[resource]) then
|
|
if maps[resource].name then
|
|
print('Started map ' .. maps[resource].name)
|
|
SetMapName(maps[resource].name)
|
|
else
|
|
print('Started map ' .. resource)
|
|
SetMapName(resource)
|
|
end
|
|
|
|
currentMap = resource
|
|
else
|
|
currentMap = nil
|
|
end
|
|
end
|
|
end
|
|
elseif gametypes[resource] then
|
|
if not getCurrentGameType() then
|
|
if TriggerEvent('onGameTypeStart', resource, gametypes[resource]) then
|
|
currentGameType = resource
|
|
|
|
local gtName = gametypes[resource].name or resource
|
|
|
|
SetGameType(gtName)
|
|
|
|
print('Started gametype ' .. gtName)
|
|
|
|
SetTimeout(50, function()
|
|
if not currentMap then
|
|
local possibleMaps = {}
|
|
|
|
for map, data in pairs(maps) do
|
|
if data.gameTypes[currentGameType] then
|
|
table.insert(possibleMaps, map)
|
|
end
|
|
end
|
|
|
|
if #possibleMaps > 0 then
|
|
local rnd = math.random(#possibleMaps)
|
|
changeMap(possibleMaps[rnd])
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
currentGameType = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- handle starting
|
|
loadMap(resource)
|
|
end)
|
|
|
|
local function handleRoundEnd()
|
|
local possibleMaps = {}
|
|
|
|
for map, data in pairs(maps) do
|
|
if data.gameTypes[currentGameType] then
|
|
table.insert(possibleMaps, map)
|
|
end
|
|
end
|
|
|
|
if #possibleMaps > 0 then
|
|
local rnd = math.random(#possibleMaps)
|
|
changeMap(possibleMaps[rnd])
|
|
end
|
|
end
|
|
|
|
AddEventHandler('mapmanager:roundEnded', function()
|
|
-- set a timeout as we don't want to return to a dead environment
|
|
SetTimeout(50, handleRoundEnd) -- not a closure as to work around some issue in neolua?
|
|
end)
|
|
|
|
function roundEnded()
|
|
SetTimeout(50, handleRoundEnd)
|
|
end
|
|
|
|
AddEventHandler('onResourceStop', function(resource)
|
|
if resource == currentGameType then
|
|
TriggerEvent('onGameTypeStop', resource)
|
|
|
|
currentGameType = nil
|
|
|
|
if currentMap then
|
|
StopResource(currentMap)
|
|
end
|
|
elseif resource == currentMap then
|
|
TriggerEvent('onMapStop', resource)
|
|
|
|
currentMap = nil
|
|
end
|
|
|
|
-- unload the map
|
|
unloadMap(resource)
|
|
end)
|
|
|
|
AddEventHandler('rconCommand', function(commandName, args)
|
|
if commandName == 'map' then
|
|
if #args ~= 1 then
|
|
RconPrint("usage: map [mapname]\n")
|
|
end
|
|
|
|
if not maps[args[1]] then
|
|
RconPrint('no such map ' .. args[1] .. "\n")
|
|
CancelEvent()
|
|
|
|
return
|
|
end
|
|
|
|
if currentGameType == nil or not doesMapSupportGameType(currentGameType, args[1]) then
|
|
local map = maps[args[1]]
|
|
local count = 0
|
|
local gt
|
|
|
|
for type, flag in pairs(map.gameTypes) do
|
|
if flag then
|
|
count = count + 1
|
|
gt = type
|
|
end
|
|
end
|
|
|
|
if count == 1 then
|
|
print("Changing map from " .. getCurrentMap() .. " to " .. args[1] .. " (gt " .. gt .. ")")
|
|
|
|
changeGameType(gt)
|
|
changeMap(args[1])
|
|
|
|
RconPrint('map ' .. args[1] .. "\n")
|
|
else
|
|
RconPrint('map ' .. args[1] .. ' does not support ' .. currentGameType .. "\n")
|
|
end
|
|
|
|
CancelEvent()
|
|
|
|
return
|
|
end
|
|
|
|
changeMap(args[1])
|
|
|
|
RconPrint('map ' .. args[1] .. "\n")
|
|
|
|
CancelEvent()
|
|
elseif commandName == 'gametype' then
|
|
if #args ~= 1 then
|
|
RconPrint("usage: gametype [name]\n")
|
|
end
|
|
|
|
if not gametypes[args[1]] then
|
|
RconPrint('no such gametype ' .. args[1] .. "\n")
|
|
CancelEvent()
|
|
|
|
return
|
|
end
|
|
|
|
changeGameType(args[1])
|
|
|
|
RconPrint('gametype ' .. args[1] .. "\n")
|
|
|
|
CancelEvent()
|
|
end
|
|
end)
|
|
|
|
function getCurrentGameType()
|
|
return currentGameType
|
|
end
|
|
|
|
function getCurrentMap()
|
|
return currentMap
|
|
end
|
|
|
|
function getMaps()
|
|
return maps
|
|
end
|
|
|
|
function changeGameType(gameType)
|
|
if currentMap and not doesMapSupportGameType(gameType, currentMap) then
|
|
StopResource(currentMap)
|
|
end
|
|
|
|
if currentGameType then
|
|
StopResource(currentGameType)
|
|
end
|
|
|
|
StartResource(gameType)
|
|
end
|
|
|
|
function changeMap(map)
|
|
if currentMap then
|
|
StopResource(currentMap)
|
|
end
|
|
|
|
StartResource(map)
|
|
end
|
|
|
|
function doesMapSupportGameType(gameType, map)
|
|
if not gametypes[gameType] then
|
|
return false
|
|
end
|
|
|
|
if not maps[map] then
|
|
return false
|
|
end
|
|
|
|
if not maps[map].gameTypes then
|
|
return true
|
|
end
|
|
|
|
return maps[map].gameTypes[gameType]
|
|
end
|