From: SmallJoker Date: Wed, 7 Aug 2019 17:16:31 +0000 (+0200) Subject: Unify wield item handling (#8677) X-Git-Tag: 5.1.0~125 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e462a9a5ef46776d974203bb44e0b89e8c980b29;p=oweals%2Fminetest.git Unify wield item handling (#8677) This moves the wield item functions to Player and the tool utils for range calculation Also 'local_inventory' was removed due to redundancy in Client --- diff --git a/src/client/client.cpp b/src/client/client.cpp index 4dc05dc09..430784b95 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -940,7 +940,7 @@ void Client::interact(u8 action, const PointedThing& pointed) NetworkPacket pkt(TOSERVER_INTERACT, 1 + 2 + 0); pkt << action; - pkt << (u16)getPlayerItem(); + pkt << myplayer->getWieldIndex(); std::ostringstream tmp_os(std::ios::binary); pointed.serialize(tmp_os); @@ -1277,19 +1277,6 @@ void Client::sendPlayerPos() Send(&pkt); } -void Client::sendPlayerItem(u16 item) -{ - LocalPlayer *myplayer = m_env.getLocalPlayer(); - if (!myplayer) - return; - - NetworkPacket pkt(TOSERVER_PLAYERITEM, 2); - - pkt << item; - - Send(&pkt); -} - void Client::removeNode(v3s16 p) { std::map modified_blocks; @@ -1349,11 +1336,14 @@ void Client::setPlayerControl(PlayerControl &control) player->control = control; } -void Client::selectPlayerItem(u16 item) +void Client::setPlayerItem(u16 item) { - m_playeritem = item; + m_env.getLocalPlayer()->setWieldIndex(item); m_inventory_updated = true; - sendPlayerItem(item); + + NetworkPacket pkt(TOSERVER_PLAYERITEM, 2); + pkt << item; + Send(&pkt); } // Returns true if the inventory of the local player has been diff --git a/src/client/client.h b/src/client/client.h index 527ae6524..8ee34a4bd 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -271,10 +271,6 @@ public: void setPlayerControl(PlayerControl &control); - void selectPlayerItem(u16 item); - u16 getPlayerItem() const - { return m_playeritem; } - // Returns true if the inventory of the local player has been // updated from the server. If it is true, it is set to false. bool getLocalInventoryUpdated(); @@ -285,6 +281,9 @@ public: Inventory* getInventory(const InventoryLocation &loc) override; void inventoryAction(InventoryAction *a) override; + // Send the item number 'item' as player item to the server + void setPlayerItem(u16 item); + const std::list &getConnectedPlayerNames() { return m_env.getPlayerNames(); @@ -454,8 +453,6 @@ private: void Receive(); void sendPlayerPos(); - // Send the item number 'item' as player item to the server - void sendPlayerItem(u16 item); void deleteAuthData(); // helper method shared with clientpackethandler @@ -506,7 +503,6 @@ private: // If 0, server init hasn't been received yet. u16 m_proto_ver = 0; - u16 m_playeritem = 0; bool m_inventory_updated = false; Inventory *m_inventory_from_server = nullptr; float m_inventory_from_server_age = 0.0f; diff --git a/src/client/game.cpp b/src/client/game.cpp index aaa4e4cb8..b7838c22f 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -744,12 +744,11 @@ protected: bool look_for_object, const v3s16 &camera_offset); void handlePointingAtNothing(const ItemStack &playerItem); void handlePointingAtNode(const PointedThing &pointed, - const ItemDefinition &playeritem_def, const ItemStack &playeritem, - const ToolCapabilities &playeritem_toolcap, f32 dtime); + 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); void handleDigging(const PointedThing &pointed, const v3s16 &nodepos, - const ToolCapabilities &playeritem_toolcap, f32 dtime); + const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime); void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, const CameraOrientation &cam); void updateProfilerGraphs(ProfilerGraph *graph); @@ -804,8 +803,8 @@ private: void updateChat(f32 dtime, const v2u32 &screensize); - bool nodePlacementPrediction(const ItemDefinition &playeritem_def, - const ItemStack &playeritem, const v3s16 &nodepos, const v3s16 &neighbourpos); + bool nodePlacementPrediction(const ItemDefinition &selected_def, + const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos); static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX]; InputHandler *input = nullptr; @@ -837,7 +836,6 @@ private: Camera *camera = nullptr; Clouds *clouds = nullptr; // Free using ->Drop() Sky *sky = nullptr; // Free using ->Drop() - Inventory *local_inventory = nullptr; Hud *hud = nullptr; Minimap *mapper = nullptr; @@ -951,7 +949,6 @@ Game::~Game() delete server; // deleted first to stop all server threads delete hud; - delete local_inventory; delete camera; delete quicktune; delete eventmgr; @@ -1349,10 +1346,8 @@ bool Game::createClient(const std::string &playername, scsf->setSky(sky); skybox = NULL; // This is used/set later on in the main run loop - local_inventory = new Inventory(itemdef_manager); - - if (!(sky && local_inventory)) { - *error_message = "Memory allocation error (sky or local inventory)"; + if (!sky) { + *error_message = "Memory allocation error sky"; errorstream << *error_message << std::endl; return false; } @@ -1384,7 +1379,7 @@ bool Game::createClient(const std::string &playername, player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; - hud = new Hud(guienv, client, player, local_inventory); + hud = new Hud(guienv, client, player, &player->inventory); if (!hud) { *error_message = "Memory error: could not create HUD"; @@ -1977,7 +1972,7 @@ void Game::processItemSelection(u16 *new_playeritem) /* Item selection using mouse wheel */ - *new_playeritem = client->getPlayerItem(); + *new_playeritem = player->getWieldIndex(); s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1, @@ -2019,7 +2014,7 @@ void Game::dropSelectedItem(bool single_item) a->count = single_item ? 1 : 0; a->from_inv.setCurrentPlayer(); a->from_list = "main"; - a->from_i = client->getPlayerItem(); + a->from_i = client->getEnv().getLocalPlayer()->getWieldIndex(); client->inventoryAction(a); } @@ -2847,19 +2842,10 @@ void Game::updateCamera(u32 busy_time, f32 dtime) */ ItemStack playeritem; { - InventoryList *mlist = local_inventory->getList("main"); - - if (mlist && client->getPlayerItem() < mlist->getSize()) - playeritem = mlist->getItem(client->getPlayerItem()); + ItemStack selected, hand; + playeritem = player->getWieldedItem(&selected, &hand); } - if (playeritem.getDefinition(itemdef_manager).name.empty()) { // override the hand - InventoryList *hlist = local_inventory->getList("hand"); - if (hlist) - playeritem = hlist->getItem(0); - } - - ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef_manager); @@ -2949,20 +2935,6 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) { LocalPlayer *player = client->getEnv().getLocalPlayer(); - ItemStack playeritem; - { - InventoryList *mlist = local_inventory->getList("main"); - - if (mlist && client->getPlayerItem() < mlist->getSize()) - playeritem = mlist->getItem(client->getPlayerItem()); - } - - const ItemDefinition &playeritem_def = - playeritem.getDefinition(itemdef_manager); - InventoryList *hlist = local_inventory->getList("hand"); - const ItemDefinition &hand_def = - hlist ? hlist->getItem(0).getDefinition(itemdef_manager) : itemdef_manager->get(""); - v3f player_position = player->getPosition(); v3f player_eye_position = player->getEyePosition(); v3f camera_position = camera->getPosition(); @@ -2978,13 +2950,11 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) Calculate what block is the crosshair pointing to */ - f32 d = playeritem_def.range; // max. distance - f32 d_hand = hand_def.range; + ItemStack selected_item, hand_item; + const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); - if (d < 0 && d_hand >= 0) - d = d_hand; - else if (d < 0) - d = 4.0; + const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager); + f32 d = BS * getToolRange(selected_def, hand_item.getDefinition(itemdef_manager)); core::line3d shootline; @@ -3010,7 +2980,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) #endif PointedThing pointed = updatePointedThing(shootline, - playeritem_def.liquids_pointable, + selected_def.liquids_pointable, !runData.ldown_for_dig, camera_offset); @@ -3074,30 +3044,20 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) else runData.repeat_rightclick_timer = 0; - if (playeritem_def.usable && input->getLeftState()) { + + if (selected_def.usable && input->getLeftState()) { if (input->getLeftClicked() && (!client->moddingEnabled() - || !client->getScript()->on_item_use(playeritem, pointed))) + || !client->getScript()->on_item_use(selected_item, pointed))) client->interact(4, pointed); } else if (pointed.type == POINTEDTHING_NODE) { - ToolCapabilities playeritem_toolcap = - playeritem.getToolCapabilities(itemdef_manager); - if (playeritem.name.empty()) { - const ToolCapabilities *handToolcap = hlist - ? &hlist->getItem(0).getToolCapabilities(itemdef_manager) - : itemdef_manager->get("").tool_capabilities; - - if (handToolcap != nullptr) - playeritem_toolcap = *handToolcap; - } - handlePointingAtNode(pointed, playeritem_def, playeritem, - playeritem_toolcap, dtime); + handlePointingAtNode(pointed, selected_item, hand_item, dtime); } else if (pointed.type == POINTEDTHING_OBJECT) { - handlePointingAtObject(pointed, playeritem, player_position, show_debug); + handlePointingAtObject(pointed, tool_item, player_position, show_debug); } else if (input->getLeftState()) { // When button is held down in air, show continuous animation runData.left_punch = true; } else if (input->getRightClicked()) { - handlePointingAtNothing(playeritem); + handlePointingAtNothing(selected_item); } runData.pointed_old = pointed; @@ -3214,8 +3174,7 @@ void Game::handlePointingAtNothing(const ItemStack &playerItem) void Game::handlePointingAtNode(const PointedThing &pointed, - const ItemDefinition &playeritem_def, const ItemStack &playeritem, - const ToolCapabilities &playeritem_toolcap, f32 dtime) + const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime) { v3s16 nodepos = pointed.node_undersurface; v3s16 neighbourpos = pointed.node_abovesurface; @@ -3229,7 +3188,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed, if (runData.nodig_delay_timer <= 0.0 && input->getLeftState() && !runData.digging_blocked && client->checkPrivilege("interact")) { - handleDigging(pointed, nodepos, playeritem_toolcap, dtime); + handleDigging(pointed, nodepos, selected_item, hand_item, dtime); } // This should be done after digging handling @@ -3281,7 +3240,8 @@ void Game::handlePointingAtNode(const PointedThing &pointed, // If the wielded item has node placement prediction, // make that happen - bool placed = nodePlacementPrediction(playeritem_def, playeritem, nodepos, + auto &def = selected_item.getDefinition(itemdef_manager); + bool placed = nodePlacementPrediction(def, selected_item, nodepos, neighbourpos); if (placed) { @@ -3289,30 +3249,30 @@ void Game::handlePointingAtNode(const PointedThing &pointed, client->interact(3, pointed); // Read the sound soundmaker->m_player_rightpunch_sound = - playeritem_def.sound_place; + def.sound_place; if (client->moddingEnabled()) - client->getScript()->on_placenode(pointed, playeritem_def); + client->getScript()->on_placenode(pointed, def); } else { soundmaker->m_player_rightpunch_sound = SimpleSoundSpec(); - if (playeritem_def.node_placement_prediction.empty() || + if (def.node_placement_prediction.empty() || nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) { client->interact(3, pointed); // Report to server } else { soundmaker->m_player_rightpunch_sound = - playeritem_def.sound_place_failed; + def.sound_place_failed; } } } } } -bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, - const ItemStack &playeritem, const v3s16 &nodepos, const v3s16 &neighbourpos) +bool Game::nodePlacementPrediction(const ItemDefinition &selected_def, + const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos) { - std::string prediction = playeritem_def.node_placement_prediction; + std::string prediction = selected_def.node_placement_prediction; const NodeDefManager *nodedef = client->ndef(); ClientMap &map = client->getEnv().getClientMap(); MapNode node; @@ -3325,7 +3285,7 @@ bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, if (!prediction.empty() && !(nodedef->get(node).rightclickable && !isKeyDown(KeyType::SNEAK))) { verbosestream << "Node placement prediction for " - << playeritem_def.name << " is " + << selected_item.name << " is " << prediction << std::endl; v3s16 p = neighbourpos; @@ -3348,7 +3308,7 @@ bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, if (!found) { errorstream << "Node placement prediction failed for " - << playeritem_def.name << " (places " + << selected_item.name << " (places " << prediction << ") - Name not known" << std::endl; return false; @@ -3411,7 +3371,7 @@ bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, if ((predicted_f.param_type_2 == CPT2_COLOR || predicted_f.param_type_2 == CPT2_COLORED_FACEDIR || predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) { - const std::string &indexstr = playeritem.metadata.getString( + const std::string &indexstr = selected_item.metadata.getString( "palette_index", 0); if (!indexstr.empty()) { s32 index = mystoi(indexstr); @@ -3450,7 +3410,7 @@ bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, } } catch (InvalidPositionException &e) { errorstream << "Node placement prediction failed for " - << playeritem_def.name << " (places " + << selected_item.name << " (places " << prediction << ") - Position not loaded" << std::endl; } @@ -3459,8 +3419,8 @@ bool Game::nodePlacementPrediction(const ItemDefinition &playeritem_def, return false; } -void Game::handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem, - const v3f &player_position, bool show_debug) +void Game::handlePointingAtObject(const PointedThing &pointed, + const ItemStack &tool_item, const v3f &player_position, bool show_debug) { std::wstring infotext = unescape_translate( utf8_to_wide(runData.selected_object->infoText())); @@ -3496,16 +3456,9 @@ void Game::handlePointingAtObject(const PointedThing &pointed, const ItemStack & // Report direct punch v3f objpos = runData.selected_object->getPosition(); v3f dir = (objpos - player_position).normalize(); - ItemStack item = playeritem; - if (playeritem.name.empty()) { - InventoryList *hlist = local_inventory->getList("hand"); - if (hlist) { - item = hlist->getItem(0); - } - } bool disable_send = runData.selected_object->directReportPunch( - dir, &item, runData.time_from_last_punch); + dir, &tool_item, runData.time_from_last_punch); runData.time_from_last_punch = 0; if (!disable_send) @@ -3519,8 +3472,9 @@ void Game::handlePointingAtObject(const PointedThing &pointed, const ItemStack & void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, - const ToolCapabilities &playeritem_toolcap, f32 dtime) + const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime) { + // See also: serverpackethandle.cpp, action == 2 LocalPlayer *player = client->getEnv().getLocalPlayer(); ClientMap &map = client->getEnv().getClientMap(); MapNode n = client->getEnv().getClientMap().getNodeNoEx(nodepos); @@ -3529,17 +3483,12 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, // cheat detection. // Get digging parameters DigParams params = getDigParams(nodedef_manager->get(n).groups, - &playeritem_toolcap); + &selected_item.getToolCapabilities(itemdef_manager)); // If can't dig, try hand if (!params.diggable) { - InventoryList *hlist = local_inventory->getList("hand"); - const ToolCapabilities *tp = hlist - ? &hlist->getItem(0).getToolCapabilities(itemdef_manager) - : itemdef_manager->get("").tool_capabilities; - - if (tp) - params = getDigParams(nodedef_manager->get(n).groups, tp); + params = getDigParams(nodedef_manager->get(n).groups, + &hand_item.getToolCapabilities(itemdef_manager)); } if (!params.diggable) { @@ -3793,29 +3742,20 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, Inventory */ - if (client->getPlayerItem() != runData.new_playeritem) - client->selectPlayerItem(runData.new_playeritem); + if (player->getWieldIndex() != runData.new_playeritem) + client->setPlayerItem(runData.new_playeritem); // Update local inventory if it has changed if (client->getLocalInventoryUpdated()) { //infostream<<"Updating local inventory"<getLocalInventory(*local_inventory); runData.update_wielded_item_trigger = true; } if (runData.update_wielded_item_trigger) { // Update wielded tool - InventoryList *mlist = local_inventory->getList("main"); - - if (mlist && (client->getPlayerItem() < mlist->getSize())) { - ItemStack item = mlist->getItem(client->getPlayerItem()); - if (item.getDefinition(itemdef_manager).name.empty()) { // override the hand - InventoryList *hlist = local_inventory->getList("hand"); - if (hlist) - item = hlist->getItem(0); - } - camera->wield(item); - } + ItemStack selected_item, hand_item; + ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); + camera->wield(tool_item); runData.update_wielded_item_trigger = false; } diff --git a/src/client/render/core.cpp b/src/client/render/core.cpp index 8c70b36c6..bf5aa6c2c 100644 --- a/src/client/render/core.cpp +++ b/src/client/render/core.cpp @@ -86,7 +86,7 @@ void RenderingCore::drawHUD() if (show_hud) { if (draw_crosshair) hud->drawCrosshair(); - hud->drawHotbar(client->getPlayerItem()); + hud->drawHotbar(client->getEnv().getLocalPlayer()->getWieldIndex()); hud->drawLuaElements(camera->getOffset()); camera->drawNametags(); if (mapper && show_minimap) diff --git a/src/content_sao.cpp b/src/content_sao.cpp index c0bc25a4d..0f1e2f435 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -896,18 +896,11 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p m_armor_groups["immortal"] = 1; } -PlayerSAO::~PlayerSAO() -{ - if(m_inventory != &m_player->inventory) - delete m_inventory; -} - void PlayerSAO::finalize(RemotePlayer *player, const std::set &privs) { assert(player); m_player = player; m_privs = privs; - m_inventory = &m_player->inventory; } v3f PlayerSAO::getEyeOffset() const @@ -1365,13 +1358,9 @@ void PlayerSAO::setBreath(const u16 breath, bool send) m_env->getGameDef()->SendPlayerBreath(this); } -Inventory* PlayerSAO::getInventory() -{ - return m_inventory; -} -const Inventory* PlayerSAO::getInventory() const +Inventory *PlayerSAO::getInventory() const { - return m_inventory; + return m_player ? &m_player->inventory : nullptr; } InventoryLocation PlayerSAO::getInventoryLocation() const @@ -1381,61 +1370,27 @@ InventoryLocation PlayerSAO::getInventoryLocation() const return loc; } -std::string PlayerSAO::getWieldList() const +u16 PlayerSAO::getWieldIndex() const { - return "main"; + return m_player->getWieldIndex(); } ItemStack PlayerSAO::getWieldedItem() const { - const Inventory *inv = getInventory(); - ItemStack ret; - const InventoryList *mlist = inv->getList(getWieldList()); - if (mlist && getWieldIndex() < (s32)mlist->getSize()) - ret = mlist->getItem(getWieldIndex()); - return ret; -} - -ItemStack PlayerSAO::getWieldedItemOrHand() const -{ - const Inventory *inv = getInventory(); - ItemStack ret; - const InventoryList *mlist = inv->getList(getWieldList()); - if (mlist && getWieldIndex() < (s32)mlist->getSize()) - ret = mlist->getItem(getWieldIndex()); - if (ret.name.empty()) { - const InventoryList *hlist = inv->getList("hand"); - if (hlist) - ret = hlist->getItem(0); - } - return ret; + ItemStack selected_item, hand_item; + return m_player->getWieldedItem(&selected_item, &hand_item); } bool PlayerSAO::setWieldedItem(const ItemStack &item) { - Inventory *inv = getInventory(); - if (inv) { - InventoryList *mlist = inv->getList(getWieldList()); - if (mlist) { - mlist->changeItem(getWieldIndex(), item); - return true; - } + InventoryList *mlist = m_player->inventory.getList(getWieldList()); + if (mlist) { + mlist->changeItem(m_player->getWieldIndex(), item); + return true; } return false; } -int PlayerSAO::getWieldIndex() const -{ - return m_wield_index; -} - -void PlayerSAO::setWieldIndex(int i) -{ - if(i != m_wield_index) { - m_wield_index = i; - } -} - void PlayerSAO::disconnected() { m_peer_id = 0; diff --git a/src/content_sao.h b/src/content_sao.h index c579474ee..beaf697e6 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -219,7 +219,7 @@ class PlayerSAO : public UnitSAO public: PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_, bool is_singleplayer); - ~PlayerSAO(); + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_PLAYER; } ActiveObjectType getSendType() const @@ -272,16 +272,13 @@ public: /* Inventory interface */ - - Inventory* getInventory(); - const Inventory* getInventory() const; + Inventory *getInventory() const; InventoryLocation getInventoryLocation() const; - std::string getWieldList() const; + void setInventoryModified() {} + std::string getWieldList() const { return "main"; } + u16 getWieldIndex() const; ItemStack getWieldedItem() const; - ItemStack getWieldedItemOrHand() const; bool setWieldedItem(const ItemStack &item); - int getWieldIndex() const; - void setWieldIndex(int i); /* PlayerSAO-specific @@ -355,7 +352,6 @@ private: RemotePlayer *m_player = nullptr; session_t m_peer_id = 0; - Inventory *m_inventory = nullptr; // Cheat prevention LagPool m_dig_pool; @@ -371,7 +367,6 @@ private: IntervalLimiter m_drowning_interval; IntervalLimiter m_node_hurt_interval; - int m_wield_index = 0; bool m_position_not_sent = false; // Cached privileges for enforcement diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index c81d15d5b..0ce785169 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -923,7 +923,7 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt) *pkt >> item; - playersao->setWieldIndex(item); + playersao->getPlayer()->setWieldIndex(item); } void Server::handleCommand_Respawn(NetworkPacket* pkt) @@ -954,20 +954,10 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt) bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what) { - PlayerSAO *playersao = player->getPlayerSAO(); - const InventoryList *hlist = playersao->getInventory()->getList("hand"); - const ItemDefinition &playeritem_def = - playersao->getWieldedItem().getDefinition(m_itemdef); - const ItemDefinition &hand_def = - hlist ? hlist->getItem(0).getDefinition(m_itemdef) : m_itemdef->get(""); - - float max_d = BS * playeritem_def.range; - float max_d_hand = BS * hand_def.range; - - if (max_d < 0 && max_d_hand >= 0) - max_d = max_d_hand; - else if (max_d < 0) - max_d = BS * 4.0f; + 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)); // Cube diagonal * 1.5 for maximal supported node extents: // sqrt(3) * 1.5 ≅ 2.6 @@ -978,7 +968,7 @@ bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std: << "d=" << d <<", max_d=" << max_d << ". ignoring." << std::endl; // Call callbacks - m_script->on_cheat(playersao, "interacted_too_far"); + m_script->on_cheat(player->getPlayerSAO(), "interacted_too_far"); return false; } return true; @@ -1050,7 +1040,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) v3f player_pos = playersao->getLastGoodPosition(); // Update wielded item - playersao->setWieldIndex(item_i); + playersao->getPlayer()->setWieldIndex(item_i); // Get pointed to node (undefined if not POINTEDTYPE_NODE) v3s16 p_under = pointed.node_undersurface; @@ -1156,7 +1146,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) if (pointed_object->isGone()) return; - ItemStack punchitem = playersao->getWieldedItemOrHand(); + ItemStack punchitem = playersao->getWieldedItem(); ToolCapabilities toolcap = punchitem.getToolCapabilities(m_itemdef); v3f dir = (pointed_object->getBasePosition() - @@ -1224,22 +1214,19 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) // Call callbacks m_script->on_cheat(playersao, "finished_unknown_dig"); } + // Get player's wielded item - ItemStack playeritem = playersao->getWieldedItemOrHand(); - ToolCapabilities playeritem_toolcap = - playeritem.getToolCapabilities(m_itemdef); + // See also: Game::handleDigging + ItemStack selected_item, hand_item; + playersao->getPlayer()->getWieldedItem(&selected_item, &hand_item); + // Get diggability and expected digging time DigParams params = getDigParams(m_nodedef->get(n).groups, - &playeritem_toolcap); + &selected_item.getToolCapabilities(m_itemdef)); // If can't dig, try hand if (!params.diggable) { - InventoryList *hlist = playersao->getInventory()->getList("hand"); - const ToolCapabilities *tp = hlist - ? &hlist->getItem(0).getToolCapabilities(m_itemdef) - : m_itemdef->get("").tool_capabilities; - - if (tp) - params = getDigParams(m_nodedef->get(n).groups, tp); + params = getDigParams(m_nodedef->get(n).groups, + &hand_item.getToolCapabilities(m_itemdef)); } // If can't dig, ignore dig if (!params.diggable) { diff --git a/src/player.cpp b/src/player.cpp index 9beeab74e..d3ba5c2c2 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -90,6 +90,29 @@ Player::~Player() clearHud(); } +void Player::setWieldIndex(u16 index) +{ + const InventoryList *mlist = inventory.getList("main"); + m_wield_index = MYMIN(index, mlist ? mlist->getSize() : 0); +} + +ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const +{ + assert(selected); + + const InventoryList *mlist = inventory.getList("main"); // TODO: Make this generic + const InventoryList *hlist = inventory.getList("hand"); + + if (mlist && m_wield_index < mlist->getSize()) + *selected = mlist->getItem(m_wield_index); + + if (hand && hlist) + *hand = hlist->getItem(0); + + // Return effective tool item + return (hand && selected->name.empty()) ? *hand : *selected; +} + u32 Player::addHud(HudElement *toadd) { MutexAutoLock lock(m_mutex); diff --git a/src/player.h b/src/player.h index 05b6fcbb5..b0c3b2574 100644 --- a/src/player.h +++ b/src/player.h @@ -173,6 +173,11 @@ public: PlayerSettings &getPlayerSettings() { return m_player_settings; } static void settingsChangedCallback(const std::string &name, void *data); + // Returns non-empty `selected` ItemStack. `hand` is a fallback, if specified + ItemStack &getWieldedItem(ItemStack *selected, ItemStack *hand) const; + void setWieldIndex(u16 index); + u16 getWieldIndex() const { return m_wield_index; } + u32 keyPressed = 0; HudElement* getHud(u32 id); @@ -185,6 +190,7 @@ public: protected: char m_name[PLAYERNAME_SIZE]; v3f m_speed; + u16 m_wield_index = 0; std::vector hud; private: diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 6d9d832b7..6345fc75f 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -210,17 +210,13 @@ int ModApiClient::l_get_language(lua_State *L) int ModApiClient::l_get_wielded_item(lua_State *L) { Client *client = getClient(L); + LocalPlayer *player = client->getEnv().getLocalPlayer(); + if (!player) + return 0; - Inventory local_inventory(client->idef()); - client->getLocalInventory(local_inventory); - - InventoryList *mlist = local_inventory.getList("main"); - - if (mlist && client->getPlayerItem() < mlist->getSize()) { - LuaItemStack::create(L, mlist->getItem(client->getPlayerItem())); - } else { - LuaItemStack::create(L, ItemStack()); - } + ItemStack selected_item; + player->getWieldedItem(&selected_item, nullptr); + LuaItemStack::create(L, selected_item); return 1; } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ad8554834..5dba63159 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -308,8 +308,9 @@ int ObjectRef::l_get_wield_list(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it + if (!co) + return 0; + lua_pushstring(L, co->getWieldList().c_str()); return 1; } @@ -320,8 +321,9 @@ int ObjectRef::l_get_wield_index(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); - if (co == NULL) return 0; - // Do it + if (!co) + return 0; + lua_pushinteger(L, co->getWieldIndex() + 1); return 1; } @@ -332,12 +334,12 @@ int ObjectRef::l_get_wielded_item(lua_State *L) NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); - if (co == NULL) { + if (!co) { // Empty ItemStack LuaItemStack::create(L, ItemStack()); return 1; } - // Do it + LuaItemStack::create(L, co->getWieldedItem()); return 1; } diff --git a/src/serverobject.h b/src/serverobject.h index 08f7a7e58..c81abb972 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -170,9 +170,7 @@ public: {} // Inventory and wielded item - virtual Inventory* getInventory() - { return NULL; } - virtual const Inventory* getInventory() const + virtual Inventory *getInventory() const { return NULL; } virtual InventoryLocation getInventoryLocation() const { return InventoryLocation(); } @@ -180,7 +178,7 @@ public: {} virtual std::string getWieldList() const { return ""; } - virtual int getWieldIndex() const + virtual u16 getWieldIndex() const { return 0; } virtual ItemStack getWieldedItem() const; virtual bool setWieldedItem(const ItemStack &item); diff --git a/src/tool.cpp b/src/tool.cpp index 09b876ae0..66bd84a8e 100644 --- a/src/tool.cpp +++ b/src/tool.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "tool.h" +#include "itemdef.h" #include "itemgroup.h" #include "log.h" #include "inventory.h" @@ -277,4 +278,16 @@ PunchDamageResult getPunchDamage( return result; } +f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand) +{ + float max_d = def_selected.range; + float max_d_hand = def_hand.range; + + if (max_d < 0 && max_d_hand >= 0) + max_d = max_d_hand; + else if (max_d < 0) + max_d = 4.0f; + + return max_d; +} diff --git a/src/tool.h b/src/tool.h index 00fae4881..d077b54ce 100644 --- a/src/tool.h +++ b/src/tool.h @@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "itemgroup.h" #include +struct ItemDefinition; + struct ToolGroupCap { std::unordered_map times; @@ -132,3 +134,5 @@ PunchDamageResult getPunchDamage( const ItemStack *punchitem, float time_from_last_punch ); + +f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand);