From b0715e57b760359be9a0fdfbd3b8e08584f9fad3 Mon Sep 17 00:00:00 2001 From: cx384 Date: Sat, 1 Feb 2025 14:12:38 +0100 Subject: [PATCH 1/2] Fix overrideable hand ToolCapabilities and range --- src/client/clientobject.h | 4 ++-- src/client/content_cao.cpp | 4 ++-- src/client/content_cao.h | 4 ++-- src/client/game.cpp | 25 +++++++++++++------------ src/inventory.h | 27 +++++++++++++++++---------- src/network/serverpackethandler.cpp | 12 ++++++------ 6 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/client/clientobject.h b/src/client/clientobject.h index 95f926928cf04..4002a8181d091 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -75,8 +75,8 @@ class ClientActiveObject : public ActiveObject Client *client, ClientEnvironment *env); // If returns true, punch will not be sent to the server - virtual bool directReportPunch(v3f dir, const ItemStack *punchitem = nullptr, - float time_from_last_punch = 1000000) { return false; } + virtual bool directReportPunch(v3f dir, const ItemStack *punchitem, + const ItemStack *hand_item, float time_from_last_punch = 1000000) { return false; } protected: // Used for creating objects based on type diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 5c044ddeffdbc..9950e1ac0e8a4 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1861,11 +1861,11 @@ void GenericCAO::processMessage(const std::string &data) /* \pre punchitem != NULL */ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem, - float time_from_last_punch) + const ItemStack *hand_item, float time_from_last_punch) { assert(punchitem); // pre-condition const ToolCapabilities *toolcap = - &punchitem->getToolCapabilities(m_client->idef()); + &punchitem->getToolCapabilities(m_client->idef(), hand_item); PunchDamageResult result = getPunchDamage( m_armor_groups, toolcap, diff --git a/src/client/content_cao.h b/src/client/content_cao.h index a6b9beeab6498..383ed1d549821 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -269,8 +269,8 @@ class GenericCAO : public ClientActiveObject void processMessage(const std::string &data) override; - bool directReportPunch(v3f dir, const ItemStack *punchitem=NULL, - float time_from_last_punch=1000000) override; + bool directReportPunch(v3f dir, const ItemStack *punchitem, + const ItemStack *hand_item, float time_from_last_punch=1000000) override; std::string debugInfoText() override; diff --git a/src/client/game.cpp b/src/client/game.cpp index 00808803f6dd1..027784193ba31 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -590,7 +590,7 @@ class Game { void handlePointingAtNode(const PointedThing &pointed, const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem, - const v3f &player_position, bool show_debug); + const ItemStack &hand_item, const v3f &player_position, bool show_debug); void handleDigging(const PointedThing &pointed, const v3s16 &nodepos, const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, @@ -2937,14 +2937,14 @@ void Game::updateCamera(f32 dtime) - Is it a usable item? - Can it point to liquids? */ - ItemStack playeritem; + ItemStack playeritem, hand; { - ItemStack selected, hand; + ItemStack selected; playeritem = player->getWieldedItem(&selected, &hand); } ToolCapabilities playeritem_toolcap = - playeritem.getToolCapabilities(itemdef_manager); + playeritem.getToolCapabilities(itemdef_manager, &hand); if (wasKeyPressed(KeyType::CAMERA_MODE)) { GenericCAO *playercao = player->getCAO(); @@ -3047,8 +3047,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud) ItemStack selected_item, hand_item; const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); - const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager); - f32 d = getToolRange(selected_item, hand_item, itemdef_manager); + const ItemDefinition &selected_def = tool_item.getDefinition(itemdef_manager); + f32 d = getToolRange(tool_item, hand_item, itemdef_manager); core::line3d shootline; @@ -3162,7 +3162,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud) } else if (pointed.type == POINTEDTHING_OBJECT) { v3f player_position = player->getPosition(); bool basic_debug_allowed = client->checkPrivilege("debug") || (player->hud_flags & HUD_FLAG_BASIC_DEBUG); - handlePointingAtObject(pointed, tool_item, player_position, + handlePointingAtObject(pointed, tool_item, hand_item, player_position, m_game_ui->m_flags.show_basic_debug && basic_debug_allowed); } else if (isKeyDown(KeyType::DIG)) { // When button is held down in air, show continuous animation @@ -3578,8 +3578,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, } } -void Game::handlePointingAtObject(const PointedThing &pointed, - const ItemStack &tool_item, const v3f &player_position, bool show_debug) +void Game::handlePointingAtObject(const PointedThing &pointed, const ItemStack &tool_item, + const ItemStack &hand_item, const v3f &player_position, bool show_debug) { std::wstring infotext = unescape_translate( utf8_to_wide(runData.selected_object->infoText())); @@ -3617,7 +3617,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed, v3f dir = (objpos - player_position).normalize(); bool disable_send = runData.selected_object->directReportPunch( - dir, &tool_item, runData.time_from_last_punch); + dir, &tool_item, &hand_item, runData.time_from_last_punch); runData.time_from_last_punch = 0; if (!disable_send) @@ -3638,13 +3638,14 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, ClientMap &map = client->getEnv().getClientMap(); MapNode n = map.getNode(nodepos); const auto &features = nodedef_manager->get(n); + const ItemStack &tool_item = selected_item.name.empty() ? hand_item : selected_item; // NOTE: Similar piece of code exists on the server side for // cheat detection. // Get digging parameters DigParams params = getDigParams(features.groups, - &selected_item.getToolCapabilities(itemdef_manager), - selected_item.wear); + &tool_item.getToolCapabilities(itemdef_manager, &hand_item), + tool_item.wear); // If can't dig, try hand if (!params.diggable) { diff --git a/src/inventory.h b/src/inventory.h index d39e9e97c62bf..41856d85cd546 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -102,18 +102,25 @@ struct ItemStack } // Get tool digging properties, or those of the hand if not a tool + // If not hand assumes default hand "" const ToolCapabilities& getToolCapabilities( - const IItemDefManager *itemdef) const + const IItemDefManager *itemdef, const ItemStack* hand = nullptr) const { - const ToolCapabilities *item_cap = - itemdef->get(name).tool_capabilities; - - if (item_cap == NULL) - // Fall back to the hand's tool capabilities - item_cap = itemdef->get("").tool_capabilities; - - assert(item_cap != NULL); - return metadata.getToolCapabilities(*item_cap); // Check for override + const ToolCapabilities *item_cap = itemdef->get(name).tool_capabilities; + + if (item_cap != nullptr) { + return metadata.getToolCapabilities(*item_cap); // Check for override + } else { // Fall back to the hand's tool capabilities + if (hand != nullptr) { + item_cap = itemdef->get(hand->name).tool_capabilities; + assert(item_cap != nullptr); + return hand->metadata.getToolCapabilities(*item_cap); + } else { + item_cap = itemdef->get("").tool_capabilities; + assert(item_cap != nullptr); + return *item_cap; + } + } } const std::optional &getWearBarParams( diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 89fe3bf227ecb..5dfadb28fa102 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -852,8 +852,8 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt) bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what) { ItemStack selected_item, hand_item; - player->getWieldedItem(&selected_item, &hand_item); - f32 max_d = BS * getToolRange(selected_item, hand_item, m_itemdef); + const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); + f32 max_d = BS * getToolRange(tool_item, hand_item, m_itemdef); // Cube diagonal * 1.5 for maximal supported node extents: // sqrt(3) * 1.5 ≅ 2.6 @@ -1061,7 +1061,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) ItemStack selected_item, hand_item; ItemStack tool_item = playersao->getWieldedItem(&selected_item, &hand_item); ToolCapabilities toolcap = - tool_item.getToolCapabilities(m_itemdef); + tool_item.getToolCapabilities(m_itemdef, &hand_item); v3f dir = (pointed_object->getBasePosition() - (playersao->getBasePosition() + playersao->getEyeOffset()) ).normalize(); @@ -1118,12 +1118,12 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) // Get player's wielded item // See also: Game::handleDigging ItemStack selected_item, hand_item; - player->getWieldedItem(&selected_item, &hand_item); + ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); // Get diggability and expected digging time DigParams params = getDigParams(m_nodedef->get(n).groups, - &selected_item.getToolCapabilities(m_itemdef), - selected_item.wear); + &tool_item.getToolCapabilities(m_itemdef, &hand_item), + tool_item.wear); // If can't dig, try hand if (!params.diggable) { params = getDigParams(m_nodedef->get(n).groups, From 842f7a491d808b3f4e73b59e65dee0b0a3129c23 Mon Sep 17 00:00:00 2001 From: cx384 Date: Wed, 5 Feb 2025 12:05:00 +0100 Subject: [PATCH 2/2] Apply suggestions --- src/client/game.cpp | 2 +- src/inventory.h | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index 027784193ba31..81a1a9a29b52d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3638,7 +3638,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, ClientMap &map = client->getEnv().getClientMap(); MapNode n = map.getNode(nodepos); const auto &features = nodedef_manager->get(n); - const ItemStack &tool_item = selected_item.name.empty() ? hand_item : selected_item; + const ItemStack &tool_item = selected_item.empty() ? hand_item : selected_item; // NOTE: Similar piece of code exists on the server side for // cheat detection. diff --git a/src/inventory.h b/src/inventory.h index 41856d85cd546..cb2c08f1e29ea 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -104,23 +104,25 @@ struct ItemStack // Get tool digging properties, or those of the hand if not a tool // If not hand assumes default hand "" const ToolCapabilities& getToolCapabilities( - const IItemDefManager *itemdef, const ItemStack* hand = nullptr) const + const IItemDefManager *itemdef, const ItemStack *hand = nullptr) const { const ToolCapabilities *item_cap = itemdef->get(name).tool_capabilities; - if (item_cap != nullptr) { + if (item_cap) { return metadata.getToolCapabilities(*item_cap); // Check for override - } else { // Fall back to the hand's tool capabilities - if (hand != nullptr) { - item_cap = itemdef->get(hand->name).tool_capabilities; - assert(item_cap != nullptr); + } + + // Fall back to the hand's tool capabilities + if (hand) { + item_cap = itemdef->get(hand->name).tool_capabilities; + if (item_cap) { return hand->metadata.getToolCapabilities(*item_cap); - } else { - item_cap = itemdef->get("").tool_capabilities; - assert(item_cap != nullptr); - return *item_cap; } } + + item_cap = itemdef->get("").tool_capabilities; + assert(item_cap); + return *item_cap; } const std::optional &getWearBarParams(