Compare commits
5 Commits
f01d731ed7
...
6b101b16e4
Author | SHA1 | Date |
---|---|---|
rnd1 | 6b101b16e4 | |
rnd1 | 3dbd5e19f4 | |
rnd1 | 21d995c083 | |
rnd1 | aa632a4e3a | |
rnd1 | 02335c4526 |
14
README
14
README
|
@ -4,7 +4,7 @@
|
|||
|
||||
-------------------------------------------------------------------------
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- it under the terms of the GNU Lesser General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
|
@ -13,15 +13,11 @@
|
|||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- You should have received a copy of the GNU Lesser General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
INSTALLATION:
|
||||
If you have 'security' enabled in minetest (secure.enable_security = true)
|
||||
then you need to add in your minetest.conf: secure.trusted_mods = anticheat
|
||||
|
||||
FEATURES:
|
||||
features:
|
||||
|
||||
0. what it does:
|
||||
- succesffuly detect noclip/fly. Its just a matter of time when someone noclipping/flying is detected.
|
||||
|
@ -30,8 +26,8 @@ FEATURES:
|
|||
|
||||
1. moderators can:
|
||||
-see full reports with coordinates of location as cheats occur
|
||||
-use /crep to see latest detected cheater
|
||||
-use /crep 1 to see detailed stats
|
||||
-use /cstats to see latest detected cheater
|
||||
-use /cdebug to see even suspected cheats to be verified later
|
||||
-use /watch NAME to spectate suspect/detected cheater, /unwatch to return to normal
|
||||
|
||||
managing moderators:
|
||||
|
|
Binary file not shown.
160
init.lua
160
init.lua
|
@ -17,7 +17,7 @@
|
|||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------
|
||||
local cheat = {};
|
||||
local version = "08/02/2017";
|
||||
local version = "09/08/2017";
|
||||
|
||||
anticheatsettings = {};
|
||||
dofile(minetest.get_modpath("anticheat").."/settings.lua")
|
||||
|
@ -86,14 +86,156 @@ local punish_cheat = function(name)
|
|||
end
|
||||
end
|
||||
|
||||
-- CHECKS
|
||||
|
||||
-- uncomment when obfuscating:
|
||||
--dofile(minetest.get_modpath("anticheat").."/anticheat_source.lua")
|
||||
|
||||
local ie = minetest.request_insecure_environment() or _G;
|
||||
local anticheat_routines = ie.loadfile(minetest.get_modpath("anticheat").."/anticheat_routines.bin")
|
||||
-- DETAILED NOCLIP CHECK
|
||||
local check_noclip = function(pos)
|
||||
local nodename = minetest.get_node(pos).name;
|
||||
local clear=true;
|
||||
if nodename ~= "air" then -- check if forbidden material!
|
||||
clear = cheat.nodelist[nodename]; -- test clip violation
|
||||
if clear == nil then clear = true end
|
||||
end
|
||||
|
||||
if not clear then -- more detailed check
|
||||
local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, {"air"});
|
||||
if #anodes == 0 then return false end
|
||||
clear=true;
|
||||
end
|
||||
return clear;
|
||||
end
|
||||
|
||||
-- DETAILED FLY CHECK
|
||||
local check_fly = function(pos) -- return true if player not flying
|
||||
local fly = (minetest.get_node(pos).name=="air" and minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name=="air"); -- prerequisite for flying is this to be "air", but not sufficient condition
|
||||
if not fly then return true end;
|
||||
|
||||
local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, {"air"});
|
||||
if #anodes == 18 then -- player standing on air?
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local round = function (x)
|
||||
if x > 0 then
|
||||
return math.floor(x+0.5)
|
||||
else
|
||||
return -math.floor(-x+0.5)
|
||||
end
|
||||
end
|
||||
|
||||
--main check routine
|
||||
local check_player = function(player)
|
||||
|
||||
local name = player:get_player_name();
|
||||
local privs = minetest.get_player_privs(name).kick;if privs then return end -- dont check moderators
|
||||
if cheat.watcher[name] then return end -- skip checking watchers while they watch
|
||||
|
||||
local pos = player:getpos(); -- feet position
|
||||
pos.x = round(pos.x*10)/10;pos.z = round(pos.z*10)/10; -- less useless clutter
|
||||
pos.y = round(pos.y*10)/10; -- minetest buggy collision - need to do this or it returns wrong materials for feet position: aka magic number 0.498?????228
|
||||
if pos.y<0 then pos.y=pos.y+1 end -- weird, without this it fails to check feet block where y<0, it checks one below feet
|
||||
|
||||
local nodename = minetest.get_node(pos).name;
|
||||
local clear=true;
|
||||
if nodename ~= "air" then -- check if forbidden material!
|
||||
clear = cheat.nodelist[nodename]; -- test clip violation
|
||||
if clear == nil then clear = true end
|
||||
end
|
||||
|
||||
local fly = (nodename=="air" and minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name=="air"); -- prerequisite for flying, but not sufficient condition
|
||||
|
||||
if cheat.players[name].count == 0 then -- player hasnt "cheated" yet, remember last clear position
|
||||
cheat.players[name].clearpos = cheat.players[name].lastpos
|
||||
end
|
||||
|
||||
|
||||
-- manage noclip cheats
|
||||
if not clear then -- player caught inside walls
|
||||
local moved = (cheat.players[name].lastpos.x~=pos.x) or (cheat.players[name].lastpos.y~=pos.y) or (cheat.players[name].lastpos.z~=pos.z);
|
||||
if moved then -- if player stands still whole time do nothing
|
||||
if cheat.players[name].count == 0 then cheat.players[name].cheatpos = pos end -- remember first position where player found inside wall
|
||||
|
||||
|
||||
if cheat.players[name].count == 0 then
|
||||
minetest.after(CHECK_AGAIN+math.random(5),
|
||||
function()
|
||||
cheat.players[name].count = 0;
|
||||
if not check_noclip(pos) then
|
||||
punish_cheat(name)-- we got a cheater!
|
||||
else
|
||||
cheat.players[name].count = 0; -- reset
|
||||
cheat.players[name].cheattype = 0;
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
if cheat.players[name].count == 0 then -- mark as suspect
|
||||
cheat.players[name].count = 1;
|
||||
cheat.players[name].cheattype = 1;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- manage flyers
|
||||
if fly then
|
||||
|
||||
local fpos;
|
||||
fly,fpos = minetest.line_of_sight(pos, {x = pos.x, y = pos.y - 4, z = pos.z}, 1); --checking node maximal jump height below feet
|
||||
|
||||
if fly then -- so we are in air, are we flying?
|
||||
|
||||
if player:get_player_control().sneak then -- player sneaks, maybe on border?
|
||||
--search 18 nodes to find non air
|
||||
local anodes = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y, z=pos.z+1}, {"air"});
|
||||
if #anodes < 18 then fly = false end
|
||||
end -- if at this point fly = true means player is not standing on border
|
||||
|
||||
if pos.y>=cheat.players[name].lastpos.y and fly then -- we actually didnt go down from last time and not on border
|
||||
|
||||
-- was lastpos in air too?
|
||||
local lastpos = cheat.players[name].lastpos;
|
||||
local anodes = minetest.find_nodes_in_area({x=lastpos.x-1, y=lastpos.y-1, z=lastpos.z-1}, {x=lastpos.x+1, y=lastpos.y, z=lastpos.z+1}, {"air"});
|
||||
if #anodes == 18 then fly = true else fly = false end
|
||||
|
||||
if fly then -- so now in air above previous position, which was in air too?
|
||||
|
||||
if cheat.players[name].count == 0 then cheat.players[name].cheatpos = pos end -- remember first position where player found "cheating"
|
||||
|
||||
if cheat.players[name].count == 0 then
|
||||
minetest.after(CHECK_AGAIN,
|
||||
function()
|
||||
cheat.players[name].count = 0;
|
||||
if not check_fly(pos) then
|
||||
punish_cheat(name)-- we got a cheater!
|
||||
else
|
||||
cheat.players[name].count = 0;
|
||||
cheat.players[name].cheattype = 0;
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
if cheat.players[name].count == 0 then -- mark as suspect
|
||||
cheat.players[name].count = 1;
|
||||
cheat.players[name].cheattype = 2;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
cheat.players[name].lastpos = pos
|
||||
end
|
||||
|
||||
check_noclip, check_fly, check_player = anticheat_routines(minetest,cheat,CHECK_AGAIN,punish_cheat);
|
||||
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
@ -271,10 +413,11 @@ minetest.register_on_joinplayer(function(player) -- init stuff on player join
|
|||
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("cchk", { -- see cheat report
|
||||
minetest.register_chatcommand("cchk", {
|
||||
privs = {
|
||||
interact = true
|
||||
},
|
||||
description = "cchk NAME, checks if player is cheating in this moment",
|
||||
func = function(name, param)
|
||||
local privs = minetest.get_player_privs(name).privs;
|
||||
if not cheat.moderators[name] and not privs then return end
|
||||
|
@ -303,6 +446,7 @@ minetest.register_chatcommand("crep", { -- see cheat report
|
|||
privs = {
|
||||
interact = true
|
||||
},
|
||||
description = "crep 0/1, 0 = default cheat report, 1 = connected player stats",
|
||||
func = function(name, param)
|
||||
local privs = minetest.get_player_privs(name).privs;
|
||||
if not cheat.moderators[name] and not privs then return end
|
||||
|
@ -438,7 +582,7 @@ end
|
|||
|
||||
minetest.register_chatcommand("watch", {
|
||||
params = "<to_name>",
|
||||
description = "",
|
||||
description = " - spectate what player is doing, stop with /unwatch",
|
||||
privs = {interact=true},
|
||||
func = function(name, param)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
|
||||
-- SETTINGS --------------------------------------------------------------
|
||||
anticheatsettings.CHEAT_TIMESTEP = 15; -- check all players
|
||||
anticheatsettings.CHEAT_TIMESTEP = 15; -- check timestep all players
|
||||
anticheatsettings.CHECK_AGAIN = 15; -- after player found in bad position check again after this to make sure its not lag, this should be larger than expected lag in seconds
|
||||
|
||||
-- moderators list, those players can use cheat debug and will see full cheat message
|
||||
|
|
Loading…
Reference in New Issue