diff --git a/config/_file_loader.lua b/config/_file_loader.lua index 16a135af..ab25db07 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -43,6 +43,7 @@ return { 'modules.addons.discord-alerts', 'modules.addons.chat-reply', 'modules.addons.tree-decon', + 'modules.addons.afk-kick', --- Data 'modules.data.statistics', diff --git a/config/afk_kick.lua b/config/afk_kick.lua new file mode 100644 index 00000000..800b9730 --- /dev/null +++ b/config/afk_kick.lua @@ -0,0 +1,9 @@ +return { + admin_as_active = true, --- @setting admin_as_active When true admins will be treated as active regardless of afk time + trust_as_active = true, --- @setting trust_as_active When true trusted players (by playtime) will be treated as active regardless of afk time + active_role = 'Veteran', --- @setting active_role When not nil a player with this role will be treated as active regardless of afk time + afk_time = 3600*10, --- @setting afk_time The time in ticks that must pass for a player to be considered afk + kick_time = 3600*30, --- @setting kick_time The time in ticks that must pass without any active players for all players to be kicked + trust_time = 3600*60*10, --- @setting trust_time The time in ticks that a player must be online for to count as trusted + update_time = 3600*30, --- @setting update_time How often in ticks the script check for active players +} \ No newline at end of file diff --git a/modules/addons/afk-kick.lua b/modules/addons/afk-kick.lua new file mode 100644 index 00000000..578e57b8 --- /dev/null +++ b/modules/addons/afk-kick.lua @@ -0,0 +1,66 @@ +--- Kicks players when all players on the server are afk +-- @addon afk-kick + +local Event = require 'utils.event' --- @dep utils.event +local Global = require 'utils.global' --- @dep utils.global +local config = require 'config.afk_kick' --- @dep config.afk_kick +local Async = require 'expcore.async' --- @dep expcore.async + +--- Optional roles require +local Roles +if config.active_role then + Roles = require 'expcore.roles' +end + +--- Globals +local primitives = { last_active = 0 } +Global.register(primitives, function(tbl) + primitives = tbl +end) + +--- Kicks an afk player, used to give to for gui to show +local kick_player = +Async.register(function(player) + if game.tick - primitives.last_active < config.kick_time then return end -- Safety Catch + game.kick_player(player, 'Afk while no active players on the server') +end) + +--- Check for an active player every 5 minutes +Event.on_nth_tick(config.update_time, function() + -- Check for active players + for _, player in ipairs(game.connected_players) do + if player.afk_time < config.afk_time + or config.admin_as_active and config.player.admin + or config.trust_as_active and player.online_time > config.trust_time + or config.active_role and Roles.player_has_role(player, config.active_role) then + -- Active player was found + primitives.last_active = game.tick + return + end + end + + -- No active player was found, check if players should be kicked + if game.tick - primitives.last_active < config.kick_time then return end + + -- Kick time exceeded, kick all players + for _, player in ipairs(game.connected_players) do + -- Add a frame to say why the player was kicked + local res = player.display_resolution + local uis = player.display_scale + player.gui.screen.add{ + type = 'frame', + name = 'afk-kick', + caption = 'All players were kicked because everyone was afk.', + }.location = { x=res.width*(0.5 - 0.11*uis), y=res.height*(0.5 - 0.14*uis) } + + -- Kick the player, some delay needed because network delay + Async.wait(10, kick_player, player) + end +end) + +--- Remove the screen gui if it is present +Event.add(defines.events.on_player_joined_game, function(event) + local player = game.get_player(event.player_index) + local frame = player.gui.screen["afk-kick"] + if frame and frame.valid then frame.destroy() end +end) \ No newline at end of file