Unify wield item handling (#8677)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Wed, 7 Aug 2019 17:16:31 +0000 (19:16 +0200)
committerGitHub <noreply@github.com>
Wed, 7 Aug 2019 17:16:31 +0000 (19:16 +0200)
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

14 files changed:
src/client/client.cpp
src/client/client.h
src/client/game.cpp
src/client/render/core.cpp
src/content_sao.cpp
src/content_sao.h
src/network/serverpackethandler.cpp
src/player.cpp
src/player.h
src/script/lua_api/l_client.cpp
src/script/lua_api/l_object.cpp
src/serverobject.h
src/tool.cpp
src/tool.h

index 4dc05dc09c064bec4853e278afca6ef342975086..430784b95de7b61cbbb6fdae02e28fd96f4fee3e 100644 (file)
@@ -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<v3s16, MapBlock*> 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
index 527ae652415551045e74c9b1a334ed985d6b6aa1..8ee34a4bd0f90eee718fa6054cf2042224505f84 100644 (file)
@@ -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<std::string> &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;
index aaa4e4cb8a4bb8ffec7c5b21f9928653542e96ac..b7838c22fc77d7168f8e14eb4638961485eda80b 100644 (file)
@@ -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<f32> 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"<<std::endl;
-               client->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;
        }
index 8c70b36c6a03d7b2da091c27f06fd41c829e12fd..bf5aa6c2c3d78508ffbfec1646107de1d49a85a5 100644 (file)
@@ -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)
index c0bc25a4d93edd71bb2401bedfc25e1fc004c87d..0f1e2f435c623f3d29362be128f48038d28765ab 100644 (file)
@@ -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<std::string> &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;
index c579474ee60fd1ee5ab85cececdff77cab049597..beaf697e632f075338ec5bda9b08701f532ba9b7 100644 (file)
@@ -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
index c81d15d5b6dbe8b37e4a4c9914e71f6eafde6af0..0ce785169673653e067330b1836a0803d4d049b6 100644 (file)
@@ -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) {
index 9beeab74e4f4da8d60bb8342af5fba69ee04d842..d3ba5c2c20e9944e531f14506e289d81fd0f7dde 100644 (file)
@@ -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);
index 05b6fcbb53e21fba10143e716311fa14d4c08380..b0c3b257407abe5a7306c56dd8249d1b330d2241 100644 (file)
@@ -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<HudElement *> hud;
 private:
index 6d9d832b75353e5cb63cf7535a17acb9e13e2a03..6345fc75f7a7b1ab87671fcfcb00e371caf855f9 100644 (file)
@@ -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;
 }
 
index ad855483462eb68d3bdcedc7ff03ff0fc1667d48..5dba631591977cf9a5c70357f64b7658b8746033 100644 (file)
@@ -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;
 }
index 08f7a7e5878e3f6c1f719a91f083ded2452ed294..c81abb972722dbfcd4cfe00751b108d8a40f42ab 100644 (file)
@@ -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);
index 09b876ae0fa5d6aaf0bbd84bae9b048ec4293d1a..66bd84a8ee6110a2ce2525bf3f26fd08003e647a 100644 (file)
@@ -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;
+}
 
index 00fae48815c865723d9dc33e07a786274f8d95a1..d077b54ce19f1160222c02c74960e2db59606437 100644 (file)
@@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "itemgroup.h"
 #include <json/json.h>
 
+struct ItemDefinition;
+
 struct ToolGroupCap
 {
        std::unordered_map<int, float> 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);