From b81948a14c138517f6a227dac5b71f0b2facb33c Mon Sep 17 00:00:00 2001
From: Wuzzy <wuzzy2@mail.ru>
Date: Thu, 6 Jan 2022 20:16:35 +0000
Subject: Fix damage wraparound if very high damage (#11872)

---
 doc/lua_api.txt                 | 2 +-
 src/script/cpp_api/s_entity.cpp | 2 +-
 src/script/cpp_api/s_entity.h   | 2 +-
 src/script/cpp_api/s_player.cpp | 2 +-
 src/script/cpp_api/s_player.h   | 2 +-
 src/tool.cpp                    | 4 +++-
 src/tool.h                      | 4 ++--
 7 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index d4dc19fdd..3edfd5bb1 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -3524,7 +3524,7 @@ Helper functions
 * `minetest.get_hit_params(groups, tool_capabilities [, time_from_last_punch [, wear]])`:
     Simulates an item that punches an object.
     Returns a table with the following fields:
-    * `hp`: How much damage the punch would cause.
+    * `hp`: How much damage the punch would cause (between -65535 and 65535).
     * `wear`: How much wear would be added to the tool (ignored for non-tools).
     Parameters:
     * `groups`: Damage groups of the object
diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp
index 746f7013e..06337b9e8 100644
--- a/src/script/cpp_api/s_entity.cpp
+++ b/src/script/cpp_api/s_entity.cpp
@@ -240,7 +240,7 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime,
 //                       tool_capabilities, direction, damage)
 bool ScriptApiEntity::luaentity_Punch(u16 id,
 		ServerActiveObject *puncher, float time_from_last_punch,
-		const ToolCapabilities *toolcap, v3f dir, s16 damage)
+		const ToolCapabilities *toolcap, v3f dir, s32 damage)
 {
 	SCRIPTAPI_PRECHECKHEADER
 
diff --git a/src/script/cpp_api/s_entity.h b/src/script/cpp_api/s_entity.h
index b52f6e447..7658ae922 100644
--- a/src/script/cpp_api/s_entity.h
+++ b/src/script/cpp_api/s_entity.h
@@ -42,7 +42,7 @@ public:
 		const collisionMoveResult *moveresult);
 	bool luaentity_Punch(u16 id,
 			ServerActiveObject *puncher, float time_from_last_punch,
-			const ToolCapabilities *toolcap, v3f dir, s16 damage);
+			const ToolCapabilities *toolcap, v3f dir, s32 damage);
 	bool luaentity_on_death(u16 id, ServerActiveObject *killer);
 	void luaentity_Rightclick(u16 id, ServerActiveObject *clicker);
 	void luaentity_on_attach_child(u16 id, ServerActiveObject *child);
diff --git a/src/script/cpp_api/s_player.cpp b/src/script/cpp_api/s_player.cpp
index d3e6138dc..22b24f363 100644
--- a/src/script/cpp_api/s_player.cpp
+++ b/src/script/cpp_api/s_player.cpp
@@ -60,7 +60,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
 		float time_from_last_punch,
 		const ToolCapabilities *toolcap,
 		v3f dir,
-		s16 damage)
+		s32 damage)
 {
 	SCRIPTAPI_PRECHECKHEADER
 	// Get core.registered_on_punchplayers
diff --git a/src/script/cpp_api/s_player.h b/src/script/cpp_api/s_player.h
index c0f141862..e866aee46 100644
--- a/src/script/cpp_api/s_player.h
+++ b/src/script/cpp_api/s_player.h
@@ -46,7 +46,7 @@ public:
 	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);
+			v3f dir, s32 damage);
 	void on_rightclickplayer(ServerActiveObject *player, ServerActiveObject *clicker);
 	s32 on_player_hpchange(ServerActiveObject *player, s32 hp_change,
 			const PlayerHPChangeReason &reason);
diff --git a/src/tool.cpp b/src/tool.cpp
index b0749286d..075c6b3c5 100644
--- a/src/tool.cpp
+++ b/src/tool.cpp
@@ -306,7 +306,7 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
 		const ToolCapabilities *tp, float time_from_last_punch,
 		u16 initial_wear)
 {
-	s16 damage = 0;
+	s32 damage = 0;
 	float result_wear = 0.0f;
 	float punch_interval_multiplier =
 			rangelim(time_from_last_punch / tp->full_punch_interval, 0.0f, 1.0f);
@@ -320,6 +320,8 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
 		result_wear = calculateResultWear(tp->punch_attack_uses, initial_wear);
 		result_wear *= punch_interval_multiplier;
 	}
+	// Keep damage in sane bounds for simplicity
+	damage = rangelim(damage, -U16_MAX, U16_MAX);
 
 	u32 wear_i = (u32) result_wear;
 	return {damage, wear_i};
diff --git a/src/tool.h b/src/tool.h
index 0e3388485..8409f59af 100644
--- a/src/tool.h
+++ b/src/tool.h
@@ -106,11 +106,11 @@ DigParams getDigParams(const ItemGroupList &groups,
 
 struct HitParams
 {
-	s16 hp;
+	s32 hp;
 	// Caused wear
 	u32 wear; // u32 because wear could be 65536 (single-use weapon)
 
-	HitParams(s16 hp_ = 0, u32 wear_ = 0):
+	HitParams(s32 hp_ = 0, u32 wear_ = 0):
 		hp(hp_),
 		wear(wear_)
 	{}
-- 
cgit v1.2.3