]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/network/serverpackethandler.cpp
Wieldhand: Specify which ItemStack to use (#8961)
[dragonfireclient.git] / src / network / serverpackethandler.cpp
index 6f17d666a7c828c5819d6712c953da6538414f03..0169a57dae833c12baae2e33637036c17797e15f 100644 (file)
@@ -298,9 +298,6 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
        infostream << "Server: Sending content to "
                        << getPlayerName(pkt->getPeerId()) << std::endl;
 
-       // Send player movement settings
-       SendMovement(pkt->getPeerId());
-
        // Send item definitions
        SendItemDef(pkt->getPeerId(), m_itemdef, protocol_version);
 
@@ -312,8 +309,20 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
        // Send media announcement
        sendMediaAnnouncement(pkt->getPeerId(), lang);
 
+       RemoteClient *client = getClient(pkt->getPeerId(), CS_InitDone);
+
+       // Send active objects
+       {
+               PlayerSAO *sao = getPlayerSAO(pkt->getPeerId());
+               if (client && sao)
+                       SendActiveObjectRemoveAdd(client, sao);
+       }
+
        // Send detached inventories
-       sendDetachedInventories(pkt->getPeerId());
+       sendDetachedInventories(pkt->getPeerId(), false);
+
+       // Send player movement settings
+       SendMovement(pkt->getPeerId());
 
        // Send time of day
        u16 time = m_env->getTimeOfDay();
@@ -323,11 +332,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
        SendCSMRestrictionFlags(pkt->getPeerId());
 
        // Warnings about protocol version can be issued here
-       if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
+       if (client->net_proto_version < LATEST_PROTOCOL_VERSION) {
                SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
-                               L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
-                               L"WITH THIS SERVER!"));
-
+                       L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
+                       L"WITH THIS SERVER!"));
        }
 }
 
@@ -386,6 +394,9 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
                        peer_id, major_ver, minor_ver, patch_ver,
                        full_ver);
 
+       if (pkt->getRemainingBytes() >= 2)
+               *pkt >> playersao->getPlayer()->formspec_version;
+
        const std::vector<std::string> &players = m_clients.getPlayerNames();
        NetworkPacket list_pkt(TOCLIENT_UPDATE_PLAYER_LIST, 0, peer_id);
        list_pkt << (u8) PLAYER_LIST_INIT << (u16) players.size();
@@ -608,10 +619,9 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
                ma->from_inv.applyCurrentPlayer(player->getName());
                ma->to_inv.applyCurrentPlayer(player->getName());
 
-               setInventoryModified(ma->from_inv, false);
-               if (ma->from_inv != ma->to_inv) {
-                       setInventoryModified(ma->to_inv, false);
-               }
+               setInventoryModified(ma->from_inv);
+               if (ma->from_inv != ma->to_inv)
+                       setInventoryModified(ma->to_inv);
 
                bool from_inv_is_current_player =
                        (ma->from_inv.type == InventoryLocation::PLAYER) &&
@@ -676,7 +686,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 
                da->from_inv.applyCurrentPlayer(player->getName());
 
-               setInventoryModified(da->from_inv, false);
+               setInventoryModified(da->from_inv);
 
                /*
                        Disable dropping items out of craftpreview
@@ -712,7 +722,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 
                ca->craft_inv.applyCurrentPlayer(player->getName());
 
-               setInventoryModified(ca->craft_inv, false);
+               setInventoryModified(ca->craft_inv);
 
                //bool craft_inv_is_current_player =
                //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
@@ -731,8 +741,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
        a->apply(this, playersao, this);
        // Eat the action
        delete a;
-
-       SendInventory(playersao);
 }
 
 void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
@@ -799,7 +807,7 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
                return;
        }
 
-       if (g_settings->getBool("enable_damage")) {
+       if (!playersao->isImmortal()) {
                if (playersao->isDead()) {
                        verbosestream << "Server::ProcessData(): Info: "
                                "Ignoring damage as player " << player->getName()
@@ -923,7 +931,7 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
 
        *pkt >> item;
 
-       playersao->setWieldIndex(item);
+       playersao->getPlayer()->setWieldIndex(item);
 }
 
 void Server::handleCommand_Respawn(NetworkPacket* pkt)
@@ -952,22 +960,12 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt)
        // the previous addition has been successfully removed
 }
 
-bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what)
+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,13 +976,13 @@ 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;
 }
 
-void Server::handleCommand_Interact(NetworkPacketpkt)
+void Server::handleCommand_Interact(NetworkPacket *pkt)
 {
        /*
                [0] u16 command
@@ -993,18 +991,14 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                [5] u32 length of the next item (plen)
                [9] serialized PointedThing
                [9 + plen] player position information
-               actions:
-               0: start digging (from undersurface) or use
-               1: stop digging (all parameters ignored)
-               2: digging completed
-               3: place block or item (to abovesurface)
-               4: use item
-               5: rightclick air ("activate")
        */
-       u8 action;
+
+       InteractAction action;
        u16 item_i;
-       *pkt >> action;
+
+       *pkt >> (u8 &)action;
        *pkt >> item_i;
+
        std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
        PointedThing pointed;
        pointed.deSerialize(tmp_is);
@@ -1050,7 +1044,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;
@@ -1083,18 +1077,18 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                Make sure the player is allowed to do it
        */
        if (!checkPriv(player->getName(), "interact")) {
-               actionstream<<player->getName()<<" attempted to interact with "
-                               <<pointed.dump()<<" without 'interact' privilege"
-                               <<std::endl;
+               actionstream << player->getName() << " attempted to interact with " <<
+                               pointed.dump() << " without 'interact' privilege" << std::endl;
+
                // Re-send block to revert change on client-side
                RemoteClient *client = getClient(pkt->getPeerId());
                // Digging completed -> under
-               if (action == 2) {
+               if (action == INTERACT_DIGGING_COMPLETED) {
                        v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
                        client->SetBlockNotSent(blockpos);
                }
                // Placement -> above
-               else if (action == 3) {
+               else if (action == INTERACT_PLACE) {
                        v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
                        client->SetBlockNotSent(blockpos);
                }
@@ -1108,10 +1102,10 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
        static thread_local const bool enable_anticheat =
                        !g_settings->getBool("disable_anticheat");
 
-       if ((action == 0 || action == 2 || action == 3 || action == 4) &&
+       if ((action == INTERACT_START_DIGGING || action == INTERACT_DIGGING_COMPLETED ||
+                       action == INTERACT_PLACE || action == INTERACT_USE) &&
                        enable_anticheat && !isSingleplayer()) {
-               float d = playersao->getEyePosition()
-                       .getDistanceFrom(pointed_pos_under);
+               float d = playersao->getEyePosition().getDistanceFrom(pointed_pos_under);
 
                if (!checkInteractDistance(player, d, pointed.dump())) {
                        // Re-send block to revert change on client-side
@@ -1131,12 +1125,12 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
        /*
                0: start digging or punch object
        */
-       if (action == 0) {
+       if (action == INTERACT_START_DIGGING) {
                if (pointed.type == POINTEDTHING_NODE) {
                        MapNode n(CONTENT_IGNORE);
                        bool pos_ok;
 
-                       n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
+                       n = m_env->getMap().getNode(p_under, &pos_ok);
                        if (!pos_ok) {
                                infostream << "Server: Not punching: Node not found."
                                                << " Adding block to emerge queue."
@@ -1156,13 +1150,10 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                        if (pointed_object->isGone())
                                return;
 
-                       actionstream<<player->getName()<<" punches object "
-                                       <<pointed.object_id<<": "
-                                       <<pointed_object->getDescription()<<std::endl;
-
-                       ItemStack punchitem = playersao->getWieldedItemOrHand();
+                       ItemStack selected_item, hand_item;
+                       ItemStack tool_item = playersao->getWieldedItem(&selected_item, &hand_item);
                        ToolCapabilities toolcap =
-                                       punchitem.getToolCapabilities(m_itemdef);
+                                       tool_item.getToolCapabilities(m_itemdef);
                        v3f dir = (pointed_object->getBasePosition() -
                                        (playersao->getBasePosition() + playersao->getEyeOffset())
                                                ).normalize();
@@ -1188,22 +1179,22 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                                                PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object));
                }
 
-       } // action == 0
+       } // action == INTERACT_START_DIGGING
 
        /*
                1: stop digging
        */
-       else if (action == 1) {
-       } // action == 1
+       else if (action == INTERACT_STOP_DIGGING) {
+       } // action == INTERACT_STOP_DIGGING
 
        /*
                2: Digging completed
        */
-       else if (action == 2) {
+       else if (action == INTERACT_DIGGING_COMPLETED) {
                // Only digging of nodes
                if (pointed.type == POINTEDTHING_NODE) {
                        bool pos_ok;
-                       MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
+                       MapNode n = m_env->getMap().getNode(p_under, &pos_ok);
                        if (!pos_ok) {
                                infostream << "Server: Not finishing digging: Node not found."
                                                << " Adding block to emerge queue."
@@ -1228,22 +1219,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) {
@@ -1290,7 +1278,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                        v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
                        RemoteClient *client = getClient(pkt->getPeerId());
                        // Send unusual result (that is, node not being removed)
-                       if (m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR) {
+                       if (m_env->getMap().getNode(p_under).getContent() != CONTENT_AIR) {
                                // Re-send block to revert change on client-side
                                client->SetBlockNotSent(blockpos);
                        }
@@ -1298,17 +1286,18 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                                client->ResendBlockIfOnWire(blockpos);
                        }
                }
-       } // action == 2
+       } // action == INTERACT_DIGGING_COMPLETED
 
        /*
                3: place block or right-click object
        */
-       else if (action == 3) {
-               ItemStack item = playersao->getWieldedItem();
+       else if (action == INTERACT_PLACE) {
+               ItemStack selected_item;
+               playersao->getWieldedItem(&selected_item, nullptr);
 
                // Reset build time counter
                if (pointed.type == POINTEDTHING_NODE &&
-                               item.getDefinition(m_itemdef).type == ITEM_NODE)
+                               selected_item.getDefinition(m_itemdef).type == ITEM_NODE)
                        getClient(pkt->getPeerId())->m_time_from_building = 0.0;
 
                if (pointed.type == POINTEDTHING_OBJECT) {
@@ -1324,14 +1313,13 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
 
                        // Do stuff
                        pointed_object->rightClick(playersao);
-               }
-               else if (m_script->item_OnPlace(
-                               item, playersao, pointed)) {
+               } else if (m_script->item_OnPlace(
+                               selected_item, playersao, pointed)) {
                        // Placement was handled in lua
 
                        // Apply returned ItemStack
-                       if (playersao->setWieldedItem(item)) {
-                               SendInventory(playersao);
+                       if (playersao->setWieldedItem(selected_item)) {
+                               SendInventory(playersao, true);
                        }
                }
 
@@ -1340,7 +1328,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                RemoteClient *client = getClient(pkt->getPeerId());
                v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
                v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
-               if (!item.getDefinition(m_itemdef).node_placement_prediction.empty()) {
+               if (!selected_item.getDefinition(m_itemdef).node_placement_prediction.empty()) {
                        client->SetBlockNotSent(blockpos);
                        if (blockpos2 != blockpos) {
                                client->SetBlockNotSent(blockpos2);
@@ -1352,43 +1340,45 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                                client->ResendBlockIfOnWire(blockpos2);
                        }
                }
-       } // action == 3
+       } // action == INTERACT_PLACE
 
        /*
                4: use
        */
-       else if (action == 4) {
-               ItemStack item = playersao->getWieldedItem();
+       else if (action == INTERACT_USE) {
+               ItemStack selected_item;
+               playersao->getWieldedItem(&selected_item, nullptr);
 
-               actionstream << player->getName() << " uses " << item.name
+               actionstream << player->getName() << " uses " << selected_item.name
                                << ", pointing at " << pointed.dump() << std::endl;
 
                if (m_script->item_OnUse(
-                               item, playersao, pointed)) {
+                               selected_item, playersao, pointed)) {
                        // Apply returned ItemStack
-                       if (playersao->setWieldedItem(item)) {
-                               SendInventory(playersao);
+                       if (playersao->setWieldedItem(selected_item)) {
+                               SendInventory(playersao, true);
                        }
                }
 
-       } // action == 4
+       } // action == INTERACT_USE
 
        /*
                5: rightclick air
        */
-       else if (action == 5) {
-               ItemStack item = playersao->getWieldedItem();
+       else if (action == INTERACT_ACTIVATE) {
+               ItemStack selected_item;
+               playersao->getWieldedItem(&selected_item, nullptr);
 
                actionstream << player->getName() << " activates "
-                               << item.name << std::endl;
+                               << selected_item.name << std::endl;
 
                if (m_script->item_OnSecondaryUse(
-                               item, playersao)) {
-                       if( playersao->setWieldedItem(item)) {
-                               SendInventory(playersao);
+                               selected_item, playersao)) {
+                       if (playersao->setWieldedItem(selected_item)) {
+                               SendInventory(playersao, true);
                        }
                }
-       }
+       } // action == INTERACT_ACTIVATE
 
 
        /*