[Client] Send only individual items in PlayerInventory packets

For a long time, whenever a PlayerInventory packet was sent, it contained all the items in the player's inventory, because that's how Koncord originally implemented it and I always had too many other priorities to go back and rework it.

From now on, clients only send PlayerInventory packet with the one item added or removed, with the single exception being trading with merchants, where the entire inventory is still sent for the time being.
pull/471/head
David Cernat 6 years ago
parent 75a64a69c7
commit 03832f933b

@ -71,12 +71,16 @@ namespace MWGui
Send an ID_OBJECT_PLACE packet every time an object is dropped into the world from
the inventory screen
Send an ID_PLAYER_INVENTORY packet about the item's removal
*/
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectPlace(dropped, true);
objectList->sendObjectPlace();
mwmp::Main::get().getLocalPlayer()->sendItemChange(dropped, count, mwmp::InventoryChanges::REMOVE);
/*
End of tes3mp addition
*/
@ -290,17 +294,6 @@ namespace MWGui
WorldItemModel drop (mouseX, mouseY);
mDragAndDrop->drop(&drop, NULL);
/*
Start of tes3mp addition
Send an ID_PLAYER_INVENTORY packet every time a player loses an item
by dropping it in the world
*/
mwmp::Main::get().getLocalPlayer()->sendInventory();
/*
End of tes3mp addition
*/
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
}
else

@ -732,7 +732,11 @@ namespace MWGui
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectDelete(object);
objectList->sendObjectDelete();
mwmp::Main::get().getLocalPlayer()->sendInventory();
// If the item is gold, make sure we get the correct value
unsigned int itemCount = object.getClass().isGold(object) ? object.getCellRef().getGoldValue() : object.getRefData().getCount();
mwmp::Main::get().getLocalPlayer()->sendItemChange(object, itemCount, mwmp::InventoryChanges::ADD);
/*
End of tes3mp addition
*/

@ -181,9 +181,9 @@ namespace MWGui
/*
Start of tes3mp addition
Send an ID_PLAYER_INVENTORY packet every time a player buys training
Send an ID_PLAYER_INVENTORY packet with the gold lost
*/
mwmp::Main::get().getLocalPlayer()->sendInventory();
mwmp::Main::get().getLocalPlayer()->sendItemChange(MWWorld::ContainerStore::sGoldId, price, mwmp::InventoryChanges::REMOVE);
/*
End of tes3mp addition
*/

@ -109,8 +109,8 @@ namespace MWMechanics
Don't add the new item to the player's inventory and instead expect the server to
add it
Before using the applyEnchantment() method, remove the old item and any money paid for
the enchantment and send the player's inventory to the server
Before using the applyEnchantment() method, send an ID_PLAYER_INVENTORY packet
removing the old item from the player's inventory
The applyEnchantment() method is where the record of the newly enchanted will be sent
to the server, causing the server to send back the player's inventory with the new item
@ -120,10 +120,10 @@ namespace MWMechanics
store.remove(mOldItemPtr, 1, player);
if (!mSelfEnchanting)
if(!mSelfEnchanting)
payForEnchantment();
mwmp::Main::get().getLocalPlayer()->sendInventory();
mwmp::Main::get().getLocalPlayer()->sendItemChange(mOldItemPtr, 1, mwmp::InventoryChanges::REMOVE);
std::string newItemId = mOldItemPtr.getClass().applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName);
/*
@ -337,6 +337,16 @@ namespace MWMechanics
store.remove(MWWorld::ContainerStore::sGoldId, getEnchantPrice(), player);
/*
Start of tes3mp addition
Send an ID_PLAYER_INVENTORY packet removing the gold from the player
*/
mwmp::Main::get().getLocalPlayer()->sendItemChange(MWWorld::ContainerStore::sGoldId, getEnchantPrice(), mwmp::InventoryChanges::REMOVE);
/*
End of tes3mp addition
*/
// add gold to NPC trading gold pool
CreatureStats& enchanterStats = mEnchanter.getClass().getCreatureStats(mEnchanter);
enchanterStats.setGoldPool(enchanterStats.getGoldPool() + getEnchantPrice());

@ -1367,6 +1367,8 @@ void LocalPlayer::sendClass()
void LocalPlayer::sendInventory()
{
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Sending entire inventory to server");
MWWorld::Ptr ptrPlayer = getPlayerPtr();
MWWorld::InventoryStore &ptrInventory = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
mwmp::Item item;
@ -1393,12 +1395,59 @@ void LocalPlayer::sendInventory()
inventoryChanges.items.push_back(item);
}
inventoryChanges.count = (unsigned int) inventoryChanges.items.size();
inventoryChanges.action = InventoryChanges::SET;
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->Send();
}
void LocalPlayer::sendItemChange(const MWWorld::Ptr& itemPtr, int count, unsigned int action)
{
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Sending item change for %s with action %i, count %i",
itemPtr.getCellRef().getRefId().c_str(), action, count);
inventoryChanges.items.clear();
mwmp::Item item;
if (itemPtr.getClass().isGold(itemPtr))
item.refId = MWWorld::ContainerStore::sGoldId;
else
item.refId = itemPtr.getCellRef().getRefId();
item.count = count;
item.charge = itemPtr.getCellRef().getCharge();
item.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge();
item.soul = itemPtr.getCellRef().getSoul();
inventoryChanges.items.push_back(item);
inventoryChanges.action = action;
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->Send();
}
void LocalPlayer::sendItemChange(const std::string& refId, int count, unsigned int action)
{
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Sending item change for %s with action %i, count %i",
refId.c_str(), action, count);
inventoryChanges.items.clear();
mwmp::Item item;
item.refId = refId;
item.count = count;
item.charge = -1;
item.enchantmentCharge = -1;
item.soul = "";
inventoryChanges.items.push_back(item);
inventoryChanges.action = action;
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_INVENTORY)->Send();
}
void LocalPlayer::sendSpellbook()
{
MWWorld::Ptr ptrPlayer = getPlayerPtr();
@ -1418,13 +1467,6 @@ void LocalPlayer::sendSpellbook()
getNetworking()->getPlayerPacket(ID_PLAYER_SPELLBOOK)->Send();
}
void LocalPlayer::sendCellStates()
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_CELL_STATE to server");
getNetworking()->getPlayerPacket(ID_PLAYER_CELL_STATE)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_CELL_STATE)->Send();
}
void LocalPlayer::sendSpellChange(std::string id, unsigned int action)
{
// Skip any bugged spells that somehow have clientside-only dynamic IDs
@ -1629,6 +1671,13 @@ void LocalPlayer::sendItemUse(const MWWorld::Ptr& itemPtr)
getNetworking()->getPlayerPacket(ID_PLAYER_ITEM_USE)->Send();
}
void LocalPlayer::sendCellStates()
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_CELL_STATE to server");
getNetworking()->getPlayerPacket(ID_PLAYER_CELL_STATE)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_CELL_STATE)->Send();
}
void LocalPlayer::clearCellStates()
{
cellStateChanges.cellStates.clear();

@ -71,8 +71,9 @@ namespace mwmp
void sendClass();
void sendInventory();
void sendItemChange(const MWWorld::Ptr& itemPtr, int count, unsigned int action);
void sendItemChange(const std::string& refId, int count, unsigned int action);
void sendSpellbook();
void sendCellStates();
void sendSpellChange(std::string id, unsigned int action);
void sendQuickKey(unsigned short slot, int type, const std::string& itemId = "");
void sendJournalEntry(const std::string& quest, int index, const MWWorld::Ptr& actor);
@ -87,6 +88,7 @@ namespace mwmp
void sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition);
void sendSelectedSpell(const std::string& newSelectedSpellId);
void sendItemUse(const MWWorld::Ptr& itemPtr);
void sendCellStates();
void clearCellStates();
void clearCurrentContainer();

@ -98,7 +98,7 @@ namespace MWScript
Send an ID_PLAYER_INVENTORY packet every time a player gains an item
through a script
*/
mwmp::Main::get().getLocalPlayer()->sendInventory();
mwmp::Main::get().getLocalPlayer()->sendItemChange(item, count, mwmp::InventoryChanges::ADD);
/*
End of tes3mp addition
*/
@ -226,7 +226,7 @@ namespace MWScript
if ((numRemoved > 0)
&& (ptr == MWMechanics::getPlayer()))
{
mwmp::Main::get().getLocalPlayer()->sendInventory();
mwmp::Main::get().getLocalPlayer()->sendItemChange(item, count, mwmp::InventoryChanges::REMOVE);
/*
End of tes3mp change (major)
*/

@ -37,7 +37,7 @@ namespace MWWorld
Send an ID_OBJECT_DELETE packet every time an item is taken from the world
by the player outside of the inventory screen
Send an ID_PLAYER_INVENTORY packet as well because of the item thus gained
Send an ID_PLAYER_INVENTORY packet as well with the item thus gained
by the player
*/
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
@ -45,7 +45,11 @@ namespace MWWorld
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
objectList->addObjectDelete(getTarget());
objectList->sendObjectDelete();
mwmp::Main::get().getLocalPlayer()->sendInventory();
// If the item is gold, make sure we get the correct value
unsigned int itemCount = getTarget().getClass().isGold(newitem) ? getTarget().getCellRef().getGoldValue() : getTarget().getRefData().getCount();
mwmp::Main::get().getLocalPlayer()->sendItemChange(getTarget(), itemCount, mwmp::InventoryChanges::ADD);
/*
End of tes3mp addition
*/

Loading…
Cancel
Save