From dae805dbc1c34046c10900ba268fb65ef7ff0207 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 25 Feb 2020 07:45:06 +0200 Subject: [PATCH] [Client] Avoid PlayerInventory packet spam when creating many potions --- apps/openmw/mwmechanics/alchemy.cpp | 28 ++++++++++++++++++++++++ apps/openmw/mwmp/LocalPlayer.cpp | 33 +++++++++++++++++++++++++++++ apps/openmw/mwmp/LocalPlayer.hpp | 2 ++ 3 files changed, 63 insertions(+) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 743f41ce3..a2266f48f 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -22,6 +22,7 @@ #include #include "../mwmp/Main.hpp" #include "../mwmp/Networking.hpp" +#include "../mwmp/LocalPlayer.hpp" #include "../mwmp/Worldstate.hpp" /* End of tes3mp addition @@ -278,6 +279,16 @@ void MWMechanics::Alchemy::removeIngredients() { iter->getContainerStore()->remove(*iter, 1, mAlchemist); + /* + Start of tes3mp addition + + Store this item removal for later sending to avoid packet spam + */ + mwmp::Main::get().getLocalPlayer()->storeItemRemoval(iter->getCellRef().getRefId(), 1); + /* + End of tes3mp addition + */ + if (iter->getRefData().getCount()<1) *iter = MWWorld::Ptr(); } @@ -524,6 +535,19 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::getReadyStatus() const MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& name, int& count) { + /* + Start of tes3mp addition + + Instead of sending an ID_PLAYER_INVENTORY packet for every ingredient removal in + ContainerStore::remove(), as that would get very spammy when many potions are created + at the same time, just avoid sending packets here and store the item removals so they + can be sent in a single packet when all the potions have been created + */ + mwmp::Main::get().getLocalPlayer()->avoidSendingInventoryPackets = true; + /* + End of tes3mp addition + */ + setPotionName(name); Result readyStatus = getReadyStatus(); @@ -551,8 +575,12 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na Send an ID_RECORD_DYNAMIC packet with the potion we've been creating now that we know its quantity + + Stop avoiding the sending of ID_PLAYER_INVENTORY packets */ mwmp::Main::get().getNetworking()->getWorldstate()->sendPotionRecord(&mStoredPotion, brewedCount); + mwmp::Main::get().getLocalPlayer()->avoidSendingInventoryPackets = false; + mwmp::Main::get().getLocalPlayer()->sendStoredItemRemovals(); /* End of tes3mp addition */ diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 226eb2c75..b11ab474c 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -44,6 +44,8 @@ using namespace mwmp; using namespace std; +std::map storedItemRemovals; + LocalPlayer::LocalPlayer() { deathTime = time(0); @@ -1453,6 +1455,32 @@ void LocalPlayer::sendItemChange(const std::string& refId, int count, unsigned i getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->Send(); } +void LocalPlayer::sendStoredItemRemovals() +{ + inventoryChanges.items.clear(); + + LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending stored item removals for LocalPlayer:"); + + for (auto storedItemRemoval : storedItemRemovals) + { + mwmp::Item item; + item.refId = storedItemRemoval.first; + item.count = storedItemRemoval.second; + item.charge = -1; + item.enchantmentCharge = -1; + item.soul = ""; + inventoryChanges.items.push_back(item); + + LOG_APPEND(TimedLog::LOG_INFO, "- %s with count %i", item.refId.c_str(), item.count); + } + + inventoryChanges.action = mwmp::InventoryChanges::ACTION_TYPE::REMOVE; + getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->Send(); + + storedItemRemovals.clear(); +} + void LocalPlayer::sendSpellbook() { MWWorld::Ptr ptrPlayer = getPlayerPtr(); @@ -1710,6 +1738,11 @@ void LocalPlayer::storeCurrentContainer(const MWWorld::Ptr &container) currentContainer.mpNum = container.getCellRef().getMpNum(); } +void LocalPlayer::storeItemRemoval(const std::string& refId, int count) +{ + storedItemRemovals[refId] = storedItemRemovals[refId] + count; +} + void LocalPlayer::playAnimation() { MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(getPlayerPtr(), diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 3f01884c4..ce500f680 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -82,6 +82,7 @@ namespace mwmp void sendItemChange(const mwmp::Item& item, unsigned int action); void sendItemChange(const MWWorld::Ptr& itemPtr, int count, unsigned int action); void sendItemChange(const std::string& refId, int count, unsigned int action); + void sendStoredItemRemovals(); void sendSpellbook(); void sendSpellChange(std::string id, unsigned int action); void sendQuickKey(unsigned short slot, int type, const std::string& itemId = ""); @@ -103,6 +104,7 @@ namespace mwmp void storeCellState(const ESM::Cell& cell, int stateType); void storeCurrentContainer(const MWWorld::Ptr& container); + void storeItemRemoval(const std::string& refId, int count); void playAnimation(); void playSpeech();