diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 0b5b40fb5..874d3e885 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -38,6 +38,7 @@ core.features = { dynamic_add_media_startup = true, dynamic_add_media_filepath = true, lsystem_decoration_type = true, + item_meta_range = true, } function core.has_feature(arg) diff --git a/doc/lua_api.md b/doc/lua_api.md index 3a5f0460e..be11a4c5d 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -2560,6 +2560,8 @@ Some of the values in the key-value store are handled specially: 0 = default, 1 = left / up, 2 = middle, 3 = right / down The default currently is the same as right/down. Example: 6 = 2 + 1*4 = middle,up +* `range`: Overrides the pointing range + Example: `meta:set_float("range", 4.2)` Example: @@ -5397,6 +5399,8 @@ Utilities dynamic_add_media_filepath = true, -- L-system decoration type (5.9.0) lsystem_decoration_type = true, + -- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0) + item_meta_range = true, } ``` @@ -8980,6 +8984,7 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and range = 4.0, -- Range of node and object pointing that is possible with this item held + -- Can be overridden with itemstack meta. liquids_pointable = false, -- If true, item can point to all liquid nodes (`liquidtype ~= "none"`), diff --git a/games/devtest/mods/testitems/init.lua b/games/devtest/mods/testitems/init.lua index ec080a7c5..bde9cc6d9 100644 --- a/games/devtest/mods/testitems/init.lua +++ b/games/devtest/mods/testitems/init.lua @@ -90,3 +90,18 @@ minetest.register_craftitem("testitems:image_meta", { return itemstack end, }) + +minetest.register_craftitem("testitems:telescope_stick", { + description = S("Telescope Stick (Increases range on use.)"), + inventory_image = "testitems_telescope_stick.png", + on_use = function(itemstack, player) + local meta = itemstack:get_meta() + local range = meta:get_float("range") + 1.2 + if range > 10 then + range = 0 + end + meta:set_float("range", range) + minetest.chat_send_player(player:get_player_name(), "Telescope Stick range set to "..range) + return itemstack + end, +}) diff --git a/games/devtest/mods/testitems/textures/testitems_telescope_stick.png b/games/devtest/mods/testitems/textures/testitems_telescope_stick.png new file mode 100644 index 000000000..88d004c4c Binary files /dev/null and b/games/devtest/mods/testitems/textures/testitems_telescope_stick.png differ diff --git a/src/client/game.cpp b/src/client/game.cpp index 3a42f2b0c..a140b730c 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1384,7 +1384,7 @@ void Game::copyServerClientCache() { // It would be possible to let the client directly read the media files // from where the server knows they are. But aside from being more complicated - // it would also *not* fill the media cache and cause slower joining of + // it would also *not* fill the media cache and cause slower joining of // remote servers. // (Imagine that you launch a game once locally and then connect to a server.) @@ -3233,7 +3233,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud) const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager); - f32 d = getToolRange(selected_def, hand_item.getDefinition(itemdef_manager)); + f32 d = getToolRange(selected_item, hand_item, itemdef_manager); core::line3d shootline; diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index f4b5a4859..6d93265eb 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -895,8 +895,7 @@ bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std: { ItemStack selected_item, hand_item; player->getWieldedItem(&selected_item, &hand_item); - f32 max_d = BS * getToolRange(selected_item.getDefinition(m_itemdef), - hand_item.getDefinition(m_itemdef)); + f32 max_d = BS * getToolRange(selected_item, hand_item, m_itemdef); // Cube diagonal * 1.5 for maximal supported node extents: // sqrt(3) * 1.5 ≅ 2.6 diff --git a/src/tool.cpp b/src/tool.cpp index 3f3c2f7bd..9b1dcc247 100644 --- a/src/tool.cpp +++ b/src/tool.cpp @@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/hex.h" #include "common/c_content.h" #include - + void ToolGroupCap::toJson(Json::Value &object) const { @@ -246,7 +246,7 @@ std::optional WearBarParams::deserializeJson(std::istream &is) blend = static_cast(blendInt); else return std::nullopt; - + const Json::Value &color_stops_object = root["color_stops"]; std::map colorStops; for (const std::string &key : color_stops_object.getMemberNames()) { @@ -491,10 +491,16 @@ PunchDamageResult getPunchDamage( return result; } -f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand) +f32 getToolRange(const ItemStack &wielded_item, const ItemStack &hand_item, + const IItemDefManager *itemdef_manager) { - float max_d = def_selected.range; - float max_d_hand = def_hand.range; + const std::string &wielded_meta_range = wielded_item.metadata.getString("range"); + const std::string &hand_meta_range = hand_item.metadata.getString("range"); + + f32 max_d = wielded_meta_range.empty() ? wielded_item.getDefinition(itemdef_manager).range : + stof(wielded_meta_range); + f32 max_d_hand = hand_meta_range.empty() ? hand_item.getDefinition(itemdef_manager).range : + stof(hand_meta_range); if (max_d < 0 && max_d_hand >= 0) max_d = max_d_hand; diff --git a/src/tool.h b/src/tool.h index 3121e907d..55a8bf914 100644 --- a/src/tool.h +++ b/src/tool.h @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include struct ItemDefinition; +class IItemDefManager; struct ToolGroupCap { @@ -179,4 +180,5 @@ PunchDamageResult getPunchDamage( ); u32 calculateResultWear(const u32 uses, const u16 initial_wear); -f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand); +f32 getToolRange(const ItemStack &wielded_item, const ItemStack &hand_item, + const IItemDefManager *itemdef_manager);