diff --git a/builtin/game/register.lua b/builtin/game/register.lua index cb0840241..e5ba88f7d 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -431,6 +431,7 @@ core.registered_on_crafts, core.register_on_craft = make_registration() core.registered_craft_predicts, core.register_craft_predict = make_registration() core.registered_on_protection_violation, core.register_on_protection_violation = make_registration() core.registered_on_item_eats, core.register_on_item_eat = make_registration() +core.registered_on_punchplayers, core.register_on_punchplayer = make_registration() -- -- Compatibility for on_mapgen_init() diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4c0baa5bc..8ade48b7b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1760,6 +1760,16 @@ Call these functions only at load time! * Called after a new player has been created * `minetest.register_on_dieplayer(func(ObjectRef))` * Called when a player dies +* `minetest.register_on_punchplayer(func(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))` + * Called when a player is punched + * `player` - ObjectRef - Player that was punched + * `hitter` - ObjectRef - Player that hit + * `time_from_last_punch`: Meant for disallowing spamming of clicks (can be nil) + * `tool_capabilities`: capability table of used tool (can be nil) + * `dir`: unit vector of direction of punch. Always defined. Points from + the puncher to the punched. + * `damage` - number that represents the damage calculated by the engine + * should return `true` to prevent the default damage mechanism * `minetest.register_on_respawnplayer(func(ObjectRef))` * Called when player is to be respawned * Called _before_ repositioning of player occurs @@ -2282,7 +2292,6 @@ These functions return the leftover itemstack. * `minetest.forceload_free_block(pos)` * stops forceloading the position `pos` - Please note that forceloaded areas are saved when the server restarts. minetest.global_exists(name) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 0aae7bbc2..c7f4b60c7 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1023,15 +1023,15 @@ int PlayerSAO::punch(v3f dir, float time_from_last_punch) { // It's best that attachments cannot be punched - if(isAttached()) + if (isAttached()) return 0; - if(!toolcap) + if (!toolcap) return 0; // No effect if PvP disabled - if(g_settings->getBool("enable_pvp") == false){ - if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER){ + if (g_settings->getBool("enable_pvp") == false) { + if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { std::string str = gob_cmd_punched(0, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); @@ -1045,14 +1045,35 @@ int PlayerSAO::punch(v3f dir, std::string punchername = "nil"; - if ( puncher != 0 ) + if (puncher != 0) punchername = puncher->getDescription(); - actionstream<<"Player "<getName()<<" punched by " - <getPlayerSAO(); - setHP(getHP() - hitparams.hp); + bool damage_handled = m_env->getScriptIface()->on_punchplayer(playersao, + puncher, time_from_last_punch, toolcap, dir, + hitparams.hp); + + if (!damage_handled) { + setHP(getHP() - hitparams.hp); + } else { // override client prediction + if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + std::string str = gob_cmd_punched(0, getHP()); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + } + + + actionstream << "Player " << m_player->getName() << " punched by " + << punchername; + if (!damage_handled) { + actionstream << ", damage " << hitparams.hp << " HP"; + } else { + actionstream << ", damage handled by lua"; + } + actionstream << std::endl; return hitparams.wear; } diff --git a/src/script/cpp_api/s_internal.h b/src/script/cpp_api/s_internal.h index 10ee1a7de..9999a584a 100644 --- a/src/script/cpp_api/s_internal.h +++ b/src/script/cpp_api/s_internal.h @@ -61,3 +61,4 @@ bool* m_variable; StackUnroller stack_unroller(L); #endif /* S_INTERNAL_H_ */ + diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp index 81bfd4505..d56766824 100644 --- a/src/script/cpp_api/s_player.cpp +++ b/src/script/cpp_api/s_player.cpp @@ -19,6 +19,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_player.h" #include "cpp_api/s_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" #include "util/string.h" void ScriptApiPlayer::on_newplayer(ServerActiveObject *player) @@ -45,6 +47,28 @@ void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player) script_run_callbacks(L, 1, RUN_CALLBACKS_MODE_FIRST); } +bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player, + ServerActiveObject *hitter, + float time_from_last_punch, + const ToolCapabilities *toolcap, + v3f dir, + s16 damage) +{ + SCRIPTAPI_PRECHECKHEADER + // Get core.registered_on_punchplayers + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_punchplayers"); + // Call callbacks + objectrefGetOrCreate(L, player); + objectrefGetOrCreate(L, hitter); + lua_pushnumber(L, time_from_last_punch); + push_tool_capabilities(L, *toolcap); + push_v3f(L, dir); + lua_pushnumber(L, damage); + script_run_callbacks(L, 6, RUN_CALLBACKS_MODE_OR); + return lua_toboolean(L, -1); +} + bool ScriptApiPlayer::on_respawnplayer(ServerActiveObject *player) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h index c77d397c4..a0f764cd5 100644 --- a/src/script/cpp_api/s_player.h +++ b/src/script/cpp_api/s_player.h @@ -23,7 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "cpp_api/s_base.h" +#include "irr_v3d.h" +struct ToolCapabilities; class ScriptApiPlayer : virtual public ScriptApiBase @@ -38,6 +40,9 @@ public: void on_joinplayer(ServerActiveObject *player); void on_leaveplayer(ServerActiveObject *player); void on_cheat(ServerActiveObject *player, const std::string &cheat_type); + bool on_punchplayer(ServerActiveObject *player, + ServerActiveObject *hitter, float time_from_last_punch, + const ToolCapabilities *toolcap, v3f dir, s16 damage); void on_playerReceiveFields(ServerActiveObject *player, const std::string &formname,