From 1e8f5ffc74c6afed38dcd93d314af0cceeb00ca9 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 9 Mar 2022 05:21:05 +0400 Subject: [PATCH] Remove too idle players --- mods/PLAYER/mcl_anticheat/init.lua | 85 +++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/mods/PLAYER/mcl_anticheat/init.lua b/mods/PLAYER/mcl_anticheat/init.lua index f4a3ac909..bd76e2818 100644 --- a/mods/PLAYER/mcl_anticheat/init.lua +++ b/mods/PLAYER/mcl_anticheat/init.lua @@ -13,6 +13,7 @@ local find_nodes_in_area = minetest.find_nodes_in_area local ceil = math.ceil local floor = math.floor +local vector_length = vector.length local distance = vector.distance @@ -20,6 +21,10 @@ local window_size = 8 local detection_interval = 1.6 local step_seconds = detection_interval / window_size local joined_players = {} +local ip_to_players = {} +local player_name_to_ip = {} +local player_doesnt_move = {} +local ban_next_time = {} local function update_settings() enable_anticheat = minetest.settings:get_bool("enable_anticheat", true) @@ -58,9 +63,15 @@ local function update_player(player_object) local noclip = #find_nodes_in_area({x = x, y = head_y, z = z}, {x = x + 1, y = head_y + 1, z = z + 1}, "group:opaque") == 8 + local velocity = player_object:get_velocity() + if vector_length(velocity) < 0.00000001 then + player_doesnt_move[name] = (player_doesnt_move[name] or 0) + 1 + else + player_doesnt_move[name] = 0 + end local player_data = { pos = pos, - velocity = player_object:get_velocity(), + velocity = velocity, air = air, noclip = noclip, } @@ -142,7 +153,24 @@ local function remove_player(player_object) if not player_object then return end local name = player_object:get_player_name() if not name then return end + local ip = player_name_to_ip[name] + player_name_to_ip[name] = nil + if ip then + local players = ip_to_players[ip] + if players then + for k, v in pairs(players) do + if v == name then + if k < #players then + players[k] = players[#players] + end + players[#players] = nil + break + end + end + end + end minetest.after(step_seconds, function() + player_doesnt_move[name] = nil joined_players[name] = nil end) end @@ -154,6 +182,50 @@ local function step() check_player(player:get_player_name()) end end + for ip, players in pairs(ip_to_players) do + if #players > 2 then + local first = players[1] + local should_be_banned = ban_next_time[ip] + if #players < 6 then + for _, player_name in pairs(players) do + if (player_doesnt_move[player_name] or 0) > 1800/step_seconds then + minetest.kick_player(player_name, "Didn't move during 30 minutes, more than 2 connections from IP " .. ip) + end + end + elseif #players < 10 then + for _, player_name in pairs(players) do + if (player_doesnt_move[player_name] or 0) > 600/step_seconds then + minetest.kick_player(player_name, "Didn't move during 10 minutes, more than 5 connections from IP " .. ip) + end + end + elseif #players < 26 then + if should_be_banned then + minetest.chat_send_all("Player " .. first .. " has been banned for having more than 9 connections at once") + minetest.ban_player(first) + else + for _, player_name in pairs(players) do + if (player_doesnt_move[player_name] or 0) > 90/step_seconds then + minetest.kick_player(player_name, "Didn't move during 1.5 minutes being connected multiple times") + ban_next_time[ip] = 1 + end + end + end + elseif #players <= 100 then + if should_be_banned then + minetest.ban_player(first) + minetest.chat_send_all("Player " .. first .. " has been banned for having more than 25 connections at once") + else + for _, player_name in pairs(players) do + minetest.kick_player(player_name, "More than 25 connections from IP address " .. ip) + end + ban_next_time[ip] = 1 + end + else + minetest.ban_player(first) + minetest.chat_send_all("Player " .. first .. " has been banned for having more than 100 connections at once") + end + end + end after(step_seconds, step) end @@ -203,4 +275,15 @@ minetest.register_on_joinplayer(update_player) minetest.register_on_leaveplayer(remove_player) +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end + local players = ip_to_players[ip] + if not players then + ip_to_players[ip] = {name} + else + players[#players + 1] = name + end + player_name_to_ip[name] = ip +end) + after(step_seconds, step)