2019-01-17 01:55:19 +02:00
local Command = require ' utils.command '
2020-09-23 12:14:36 +02:00
local Rank = require ' features.rank_system '
2019-01-17 01:55:19 +02:00
local Task = require ' utils.task '
local Token = require ' utils.token '
local Server = require ' features.server '
local Popup = require ' features.gui.popup '
local Global = require ' utils.global '
2019-01-30 05:52:43 +02:00
local Ranks = require ' resources.ranks '
2019-01-17 01:55:19 +02:00
2020-10-01 22:08:09 +02:00
local Public = { }
function Public . control ( config )
2019-01-17 01:55:19 +02:00
local server_player = { name = ' <server> ' , print = print }
local global_data = { restarting = nil }
Global.register (
global_data ,
function ( tbl )
global_data = tbl
end
)
local function double_print ( str )
game.print ( str )
print ( str )
end
local callback
callback =
Token.register (
function ( data )
if not global_data.restarting then
return
end
local state = data.state
if state == 0 then
Server.start_scenario ( data.scenario_name )
double_print ( ' restarting ' )
2020-04-16 00:03:51 +02:00
global_data.restarting = nil
2019-01-17 01:55:19 +02:00
return
elseif state == 1 then
2020-10-22 19:56:53 +02:00
local game_seconds = math.floor ( game.ticks_played / 60 ) -- should probably account for game speed changes, but we rarely (if ever?) change crash site performance scale. This is good enough?
local game_hours = math.floor ( game_seconds / 3600 )
local game_min_remainder = math.floor ( ( game_seconds - ( game_hours * 3600 ) ) / 60 )
Server.to_discord_raw ( ' <@&762441731194748958> Crash Site has just restarted!! Previous map lasted: ' .. game_hours .. ' hours, ' .. game_min_remainder .. ' minutes ' )
2019-01-17 01:55:19 +02:00
Popup.all ( ' \n Server restarting! \n Initiated by ' .. data.name .. ' \n ' )
end
double_print ( state )
data.state = state - 1
Task.set_timeout_in_ticks ( 60 , callback , data )
end
)
2020-10-10 11:41:25 +02:00
local static_entities_to_check = {
2020-10-01 22:08:09 +02:00
' spitter-spawner ' , ' biter-spawner ' ,
2020-10-01 22:52:47 +02:00
' small-worm-turret ' , ' medium-worm-turret ' , ' big-worm-turret ' , ' behemoth-worm-turret ' ,
' gun-turret ' , ' laser-turret ' , ' artillery-turret ' , ' flamethrower-turret '
2020-10-01 22:08:09 +02:00
}
2020-10-10 14:07:22 +02:00
2020-10-10 11:41:25 +02:00
local biter_entities_to_check = {
' small-spitter ' , ' medium-spitter ' , ' big-spitter ' , ' behemoth-spitter ' ,
' small-biter ' , ' medium-biter ' , ' big-biter ' , ' behemoth-biter '
}
2020-10-01 22:08:09 +02:00
2020-10-10 11:41:25 +02:00
local function map_cleared ( player )
player = player or server_player
2020-10-01 22:08:09 +02:00
local get_entity_count = game.forces [ " enemy " ] . get_entity_count
2020-10-10 11:41:25 +02:00
-- Check how many of each turrets, worms and spawners are left and return false if there are any of each left.
for i = 1 , # static_entities_to_check do
local name = static_entities_to_check [ i ]
2020-10-01 22:08:09 +02:00
if get_entity_count ( name ) > 0 then
2020-10-10 14:07:22 +02:00
player.print ( ' All enemy spawners, worms, buildings, biters and spitters must be cleared before crashsite can be restarted. ' )
2020-10-01 22:08:09 +02:00
return false
end
end
2020-10-10 11:41:25 +02:00
-- Count all the remaining biters and spitters
local biter_total = 0 ;
for i = 1 , # biter_entities_to_check do
2020-10-10 14:07:22 +02:00
local name = biter_entities_to_check [ i ]
2020-10-10 11:41:25 +02:00
biter_total = biter_total + get_entity_count ( name )
end
-- Return false if more than 20 left. Players have had problems finding the last few biters so set to a reasonable value.
if biter_total > 20 then
2020-10-10 14:07:22 +02:00
player.print ( ' All enemy spawners, worms, buildings are dead. Crashsite can be restarted when all biters and spitters are killed. ' )
2020-10-10 11:41:25 +02:00
return false
end
2020-10-01 22:08:09 +02:00
return true
end
2019-03-06 23:35:38 +02:00
local function restart ( args , player )
player = player or server_player
2020-10-01 22:08:09 +02:00
local sanitised_scenario = args.scenario_name
2019-03-06 23:35:38 +02:00
if global_data.restarting then
player.print ( ' Restart already in progress ' )
return
end
2020-10-01 22:52:47 +02:00
if player ~= server_player and Rank.less_than ( player.name , Ranks.admin ) then
-- Check enemy count
2020-10-10 11:41:25 +02:00
if not map_cleared ( player ) then
2020-09-23 12:14:36 +02:00
return
2020-10-01 22:52:47 +02:00
end
2020-10-01 22:08:09 +02:00
-- Limit the ability of non-admins to call the restart function with arguments to change the scenario
-- If not an admin, restart the same scenario always
sanitised_scenario = config.scenario_name
2020-09-23 12:14:36 +02:00
end
2020-10-01 22:52:47 +02:00
2019-03-06 23:35:38 +02:00
global_data.restarting = true
double_print ( ' #################-Attention-################# ' )
double_print ( ' Server restart initiated by ' .. player.name )
double_print ( ' ########################################### ' )
2020-10-03 16:32:57 +02:00
for _ , p in pairs ( game.players ) do
if p.admin then
p.print ( ' Abort restart with /abort ' )
2019-03-06 23:35:38 +02:00
end
end
print ( ' Abort restart with /abort ' )
2020-10-01 22:52:47 +02:00
2020-10-01 22:08:09 +02:00
Task.set_timeout_in_ticks ( 60 , callback , { name = player.name , scenario_name = sanitised_scenario , state = 10 } )
2019-03-06 23:35:38 +02:00
end
local function abort ( _ , player )
player = player or server_player
if global_data.restarting then
global_data.restarting = nil
double_print ( ' Restart aborted by ' .. player.name )
else
player.print ( ' Cannot abort a restart that is not in progress. ' )
end
end
Command.add (
' crash-site-restart-abort ' ,
{
description = { ' command_description.crash_site_restart_abort ' } ,
required_rank = Ranks.admin ,
allowed_by_server = true
} ,
abort
)
2019-01-17 01:55:19 +02:00
Command.add (
2019-03-06 23:35:38 +02:00
' abort ' ,
2019-01-17 01:55:19 +02:00
{
2019-03-04 00:13:56 +02:00
description = { ' command_description.crash_site_restart_abort ' } ,
2019-01-30 05:52:43 +02:00
required_rank = Ranks.admin ,
2019-01-17 01:55:19 +02:00
allowed_by_server = true
} ,
2019-03-06 23:35:38 +02:00
abort
2019-01-17 01:55:19 +02:00
)
2019-07-28 12:44:13 +02:00
local default_name = config.scenario_name or ' crashsite '
Command.add (
' crash-site-restart ' ,
{
description = { ' command_description.crash_site_restart ' } ,
arguments = { ' scenario_name ' } ,
default_values = { scenario_name = default_name } ,
required_rank = Ranks.admin ,
allowed_by_server = true
} ,
restart
)
Command.add (
' restart ' ,
{
description = { ' command_description.crash_site_restart ' } ,
arguments = { ' scenario_name ' } ,
default_values = { scenario_name = default_name } ,
2020-09-25 12:30:48 +02:00
required_rank = Ranks.auto_trusted ,
2019-07-28 12:44:13 +02:00
allowed_by_server = true
} ,
restart
)
end
return Public