Allow mods to listen to cheat detections using minetest.register_on_cheat()
authorPerttu Ahola <celeron55@gmail.com>
Sat, 3 Aug 2013 21:45:49 +0000 (00:45 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Sat, 3 Aug 2013 21:45:49 +0000 (00:45 +0300)
builtin/misc_register.lua
doc/lua_api.txt
src/content_sao.cpp
src/content_sao.h
src/script/cpp_api/s_player.cpp
src/script/cpp_api/s_player.h
src/server.cpp

index 2d25568b61cca60e14128afe724324766a0386a9..d5e0867024c4f739da8b3b0943122ef1d2974a28 100644 (file)
@@ -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()
 
index 67ff823dad0af065d155b868da3dff18e697a45e..d3458878623de799bf3fa8d8b2453879f339b743 100644 (file)
@@ -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))
index 8d46d423729445241d267d3ee6b3c0280f49a20a..799c279a4969bea6833ee986d6535561cff185db 100644 (file)
@@ -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()
                                        <<std::endl;
                        m_player->setPosition(m_last_good_position);
                        m_moved = true;
+                       cheated = true;
                }
        }
+       return cheated;
 }
 
 bool PlayerSAO::getCollisionBox(aabb3f *toset) {
index 9640e5f0883d4a40bb708ebc86f7593acea62fcc..413fd3e683331864103164533b61eeefa1585ff7 100644 (file)
@@ -262,7 +262,8 @@ public:
        {
                return m_dig_pool;
        }
-       void checkMovementCheat();
+       // Returns true if cheated
+       bool checkMovementCheat();
 
        // Other
 
index e736d745de4053c6c822773613ead4e665cbcb86..0dbd52527ad58ea3a652c94092324969f1c4f732 100644 (file)
@@ -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<std::string, std::string> &fields)
index 663e3c2abc851c5281f7f52e1778072e0f6abae1..c0409a481e7f45130a4c37425349c46e1d2adcfa 100644 (file)
@@ -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,
index cdd42c2e9f2befca7cc981fe79c27889d6494891..7527f172cc3b2f459b077c41768e7ead202ee85d 100644 (file)
@@ -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 "<<peer_id<<" to "
                                <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
@@ -2811,6 +2815,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                RemoteClient *client = getClient(peer_id);
                                v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
                                client->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)
                                                                <<PP(nocheat_p)<<" and completed digging "
                                                                <<PP(p_under)<<"; not digging."<<std::endl;
                                                is_valid_dig = false;
+                                               // Call callbacks
+                                               m_script->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."
                                                                <<std::endl;
                                                is_valid_dig = false;
+                                               // Call callbacks
+                                               m_script->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 "<<PP(p_under)
                                                                <<"too fast; not digging."<<std::endl;
                                                is_valid_dig = false;
+                                               // Call callbacks
+                                               m_script->on_cheat(playersao, "dug_too_fast");
                                        }
                                }