+diff --git a/builtin/game/register.lua b/builtin/game/register.lua
+index ec6f280..ab1b070 100644
+--- a/builtin/game/register.lua
++++ b/builtin/game/register.lua
+@@ -553,6 +553,7 @@ 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()
++core.registered_on_rightclickplayers, core.register_on_rightclickplayer = make_registration()
+ -- Compatibility for on_mapgen_init()
+diff --git a/src/content_sao.cpp b/src/content_sao.cpp
+index be1c52f..cc57cf3 100644
+--- a/src/content_sao.cpp
++++ b/src/content_sao.cpp
+@@ -1244,6 +1244,15 @@ int PlayerSAO::punch(v3f dir,
++void PlayerSAO::rightClick(ServerActiveObject *clicker)
++ PlayerSAO *playersao = m_player->getPlayerSAO();
++ m_env->getScriptIface()->on_rightclickplayer(playersao, clicker);
+ s16 PlayerSAO::readDamage()
+diff --git a/src/content_sao.h b/src/content_sao.h
+index 0dad548..8d0fc33 100644
+@@ -238,7 +238,7 @@ class PlayerSAO : public UnitSAO
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
+ float time_from_last_punch);
+- void rightClick(ServerActiveObject *clicker) {}
++ void rightClick(ServerActiveObject *clicker);
+ void setHPRaw(s16 hp) { m_hp = hp; }
+diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp
+index a8c0747..04f607c 100644
+--- a/src/script/cpp_api/s_player.cpp
++++ b/src/script/cpp_api/s_player.cpp
+@@ -69,6 +69,19 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
+ return lua_toboolean(L, -1);
++void ScriptApiPlayer::on_rightclickplayer(ServerActiveObject *player,
++ ServerActiveObject *clicker)
++ SCRIPTAPI_PRECHECKHEADER
++ // Get core.registered_on_rightclickplayers
++ lua_getglobal(L, "core");
++ lua_getfield(L, -1, "registered_on_rightclickplayers");
++ objectrefGetOrCreate(L, player);
++ objectrefGetOrCreate(L, clicker);
++ runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
+ s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
+diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
+index 9b4611f..92ef52b 100644
+--- a/src/script/cpp_api/s_player.h
++++ b/src/script/cpp_api/s_player.h
+@@ -42,6 +42,7 @@ class ScriptApiPlayer : virtual public ScriptApiBase
+ bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter,
+ float time_from_last_punch, const ToolCapabilities *toolcap,
++ void on_rightclickplayer(ServerActiveObject *player, ServerActiveObject *clicker);
+ s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change);
+ void on_playerReceiveFields(ServerActiveObject *player,
+ const std::string &formname, const StringMap &fields);