diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua index 2d25568b6..d5e086702 100644 --- a/builtin/misc_register.lua +++ b/builtin/misc_register.lua @@ -319,4 +319,5 @@ minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make minetest.registered_on_joinplayers, minetest.register_on_joinplayer = make_registration() minetest.registered_on_leaveplayers, minetest.register_on_leaveplayer = make_registration() minetest.registered_on_player_receive_fields, minetest.register_on_player_receive_fields = make_registration_reverse() +minetest.registered_on_cheats, minetest.register_on_cheat = make_registration() diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 67ff823da..d34588786 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1142,6 +1142,9 @@ minetest.register_on_joinplayer(func(ObjectRef)) ^ Called when a player joins the game minetest.register_on_leaveplayer(func(ObjectRef)) ^ Called when a player leaves the game +minetest.register_on_cheat(func(ObjectRef, cheat)) +^ Called when a player cheats +^ cheat: {type="moved_too_fast"/"interacted_too_far"/"finished_unknown_dig"/"dug_unbreakable"/"dug_too_fast"} minetest.register_on_chat_message(func(name, message)) ^ Called always when a player says something minetest.register_on_player_receive_fields(func(player, formname, fields)) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 8d46d4237..799c279a4 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1454,8 +1454,9 @@ std::string PlayerSAO::getPropertyPacket() return gob_cmd_set_properties(m_prop); } -void PlayerSAO::checkMovementCheat() +bool PlayerSAO::checkMovementCheat() { + bool cheated = false; if(isAttached() || m_is_singleplayer || g_settings->getBool("disable_anticheat")) { @@ -1503,8 +1504,10 @@ void PlayerSAO::checkMovementCheat() <setPosition(m_last_good_position); m_moved = true; + cheated = true; } } + return cheated; } bool PlayerSAO::getCollisionBox(aabb3f *toset) { diff --git a/src/content_sao.h b/src/content_sao.h index 9640e5f08..413fd3e68 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -262,7 +262,8 @@ public: { return m_dig_pool; } - void checkMovementCheat(); + // Returns true if cheated + bool checkMovementCheat(); // Other diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index e736d745d..0dbd52527 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -81,6 +81,22 @@ void ScriptApiPlayer::on_leaveplayer(ServerActiveObject *player) runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } +void ScriptApiPlayer::on_cheat(ServerActiveObject *player, + const std::string &cheat_type) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_cheats + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_cheats"); + // Call callbacks + objectrefGetOrCreate(player); + lua_newtable(L); + lua_pushlstring(L, cheat_type.c_str(), cheat_type.size()); + lua_setfield(L, -2, "type"); + runCallbacks(2, RUN_CALLBACKS_MODE_FIRST); +} + void ScriptApiPlayer::on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, const std::map &fields) diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index 663e3c2ab..c0409a481 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -34,6 +34,7 @@ public: bool on_respawnplayer(ServerActiveObject *player); void on_joinplayer(ServerActiveObject *player); void on_leaveplayer(ServerActiveObject *player); + void on_cheat(ServerActiveObject *player, const std::string &cheat_type); void on_playerReceiveFields(ServerActiveObject *player, const std::string &formname, diff --git a/src/server.cpp b/src/server.cpp index cdd42c2e9..7527f172c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2251,7 +2251,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) player->control.LMB = (bool)(keyPressed&128); player->control.RMB = (bool)(keyPressed&256); - playersao->checkMovementCheat(); + bool cheated = playersao->checkMovementCheat(); + if(cheated){ + // Call callbacks + m_script->on_cheat(playersao, "moved_too_fast"); + } /*infostream<<"Server::ProcessData(): Moved player "<SetBlockNotSent(blockpos); + // Call callbacks + m_script->on_cheat(playersao, "interacted_too_far"); // Do nothing else return; } @@ -2939,6 +2945,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <on_cheat(playersao, "finished_unknown_dig"); } // Get player's wielded item ItemStack playeritem; @@ -2964,6 +2972,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<", which is not diggable with tool. not digging." <on_cheat(playersao, "dug_unbreakable"); } // Check digging time // If already invalidated, we don't have to @@ -2987,6 +2997,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" completed digging "<on_cheat(playersao, "dug_too_fast"); } }