From f80f3bd484794fa7df7c17d901e05580add1b104 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 1 Apr 2018 10:00:39 +0300 Subject: [PATCH] [Client] Make it possible to reply to requests about specific containers Previously, a Container packet with a REQUEST action always made the client respond with the contents of all the containers in that cell. The previous behavior now only happens for requests that have no WorldObjects attached, while requests that have WorldObjects attached get a reply with the contents of those specific containers. --- apps/openmw/mwmp/WorldEvent.cpp | 116 +++++++++++------- apps/openmw/mwmp/WorldEvent.hpp | 12 +- .../processors/world/ProcessorContainer.hpp | 28 ++++- 3 files changed, 103 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index 21450d177..f0a86aab5 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -62,6 +62,43 @@ void WorldEvent::addObject(WorldObject worldObject) worldObjects.push_back(worldObject); } +WorldObject WorldEvent::getWorldObject(const MWWorld::Ptr& ptr) +{ + mwmp::WorldObject worldObject; + worldObject.refId = ptr.getCellRef().getRefId(); + worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex; + worldObject.mpNum = ptr.getCellRef().getMpNum(); + return worldObject; +} + +void WorldEvent::addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount) +{ + mwmp::ContainerItem containerItem; + containerItem.refId = itemPtr.getCellRef().getRefId(); + containerItem.count = itemPtr.getRefData().getCount(); + containerItem.charge = itemPtr.getCellRef().getCharge(); + containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge(); + containerItem.actionCount = actionCount; + + LOG_APPEND(Log::LOG_INFO, "- Adding container item %s", containerItem.refId.c_str()); + + worldObject.containerItems.push_back(containerItem); +} + +void WorldEvent::addEntireContainer(const MWWorld::Ptr& ptr) +{ + MWWorld::ContainerStore& containerStore = ptr.getClass().getContainerStore(ptr); + + mwmp::WorldObject worldObject = getWorldObject(ptr); + + for (const auto itemPtr : containerStore) + { + addContainerItem(worldObject, itemPtr, itemPtr.getRefData().getCount()); + } + + addObject(worldObject); +} + void WorldEvent::editContainers(MWWorld::CellStore* cellStore) { bool isLocalEvent = guid == Main::get().getLocalPlayer()->guid; @@ -678,39 +715,45 @@ void WorldEvent::playVideo() } } -WorldObject WorldEvent::getWorldObject(const MWWorld::Ptr& ptr) +void WorldEvent::addAllContainers(MWWorld::CellStore* cellStore) { - mwmp::WorldObject worldObject; - worldObject.refId = ptr.getCellRef().getRefId(); - worldObject.refNumIndex = ptr.getCellRef().getRefNum().mIndex; - worldObject.mpNum = ptr.getCellRef().getMpNum(); - return worldObject; -} + MWWorld::CellRefList *containerList = cellStore->getContainers(); -void WorldEvent::addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount) -{ - mwmp::ContainerItem containerItem; - containerItem.refId = itemPtr.getCellRef().getRefId(); - containerItem.count = itemPtr.getRefData().getCount(); - containerItem.charge = itemPtr.getCellRef().getCharge(); - containerItem.enchantmentCharge = itemPtr.getCellRef().getEnchantmentCharge(); - containerItem.actionCount = actionCount; + for (auto &container : containerList->mList) + { + mwmp::WorldObject worldObject; + worldObject.refId = container.mRef.getRefId(); + worldObject.refNumIndex = container.mRef.getRefNum().mIndex; + worldObject.mpNum = container.mRef.getMpNum(); - worldObject.containerItems.push_back(containerItem); + MWWorld::ContainerStore& containerStore = container.mClass->getContainerStore(MWWorld::Ptr(&container, 0)); + + for (const auto itemPtr : containerStore) + { + addContainerItem(worldObject, itemPtr, 0); + } + + addObject(worldObject); + } } -void WorldEvent::addEntireContainer(const MWWorld::Ptr& ptr) +void WorldEvent::addRequestedContainers(MWWorld::CellStore* cellStore, const std::vector& requestObjects) { - MWWorld::ContainerStore& containerStore = ptr.getClass().getContainerStore(ptr); + for (const auto &worldObject : requestObjects) + { + LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i", worldObject.refId.c_str(), + worldObject.refNumIndex, worldObject.mpNum); - mwmp::WorldObject worldObject = getWorldObject(ptr); + MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum); - for (const auto itemPtr : containerStore) - { - addContainerItem(worldObject, itemPtr, itemPtr.getRefData().getCount()); + if (ptrFound) + { + if (ptrFound.getClass().hasContainerStore(ptrFound)) + addEntireContainer(ptrFound); + else + LOG_APPEND(Log::LOG_VERBOSE, "-- Object lacks container store", ptrFound.getCellRef().getRefId().c_str()); + } } - - addObject(worldObject); } void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer) @@ -1083,30 +1126,9 @@ void WorldEvent::sendScriptGlobalShort() mwmp::Main::get().getNetworking()->getWorldPacket(ID_SCRIPT_GLOBAL_SHORT)->Send(); } -void WorldEvent::sendCellContainers(MWWorld::CellStore* cellStore) +void WorldEvent::sendContainer() { - reset(); - cell = *cellStore->getCell(); - action = BaseEvent::SET; - - MWWorld::CellRefList *containerList = cellStore->getContainers(); - - for (auto &container : containerList->mList) - { - mwmp::WorldObject worldObject; - worldObject.refId = container.mRef.getRefId(); - worldObject.refNumIndex = container.mRef.getRefNum().mIndex; - worldObject.mpNum = container.mRef.getMpNum(); - - MWWorld::ContainerStore& containerStore = container.mClass->getContainerStore(MWWorld::Ptr(&container, 0)); - - for (const auto itemPtr : containerStore) - { - addContainerItem(worldObject, itemPtr, 0); - } - - addObject(worldObject); - } + LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Sending ID_CONTAINER"); mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->setEvent(this); mwmp::Main::get().getNetworking()->getWorldPacket(ID_CONTAINER)->Send(); diff --git a/apps/openmw/mwmp/WorldEvent.hpp b/apps/openmw/mwmp/WorldEvent.hpp index 416a0efb8..7ef4e7dbf 100644 --- a/apps/openmw/mwmp/WorldEvent.hpp +++ b/apps/openmw/mwmp/WorldEvent.hpp @@ -16,7 +16,11 @@ namespace mwmp virtual ~WorldEvent(); void reset(); + void addObject(WorldObject worldObject); + WorldObject getWorldObject(const MWWorld::Ptr& ptr); + void addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount); + void addEntireContainer(const MWWorld::Ptr& ptr); void editContainers(MWWorld::CellStore* cellStore); @@ -41,9 +45,8 @@ namespace mwmp void playMusic(); void playVideo(); - WorldObject getWorldObject(const MWWorld::Ptr& ptr); - void addContainerItem(mwmp::WorldObject& worldObject, const MWWorld::Ptr& itemPtr, int actionCount); - void addEntireContainer(const MWWorld::Ptr& ptr); + void addAllContainers(MWWorld::CellStore* cellStore); + void addRequestedContainers(MWWorld::CellStore* cellStore, const std::vector& requestObjects); void addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer = false); void addObjectSpawn(const MWWorld::Ptr& ptr); @@ -78,8 +81,7 @@ namespace mwmp void sendScriptLocalFloat(); void sendScriptMemberShort(); void sendScriptGlobalShort(); - - void sendCellContainers(MWWorld::CellStore* cellStore); + void sendContainer(); private: Networking *getNetworking(); diff --git a/apps/openmw/mwmp/processors/world/ProcessorContainer.hpp b/apps/openmw/mwmp/processors/world/ProcessorContainer.hpp index fa6c5668f..bce080716 100644 --- a/apps/openmw/mwmp/processors/world/ProcessorContainer.hpp +++ b/apps/openmw/mwmp/processors/world/ProcessorContainer.hpp @@ -21,10 +21,36 @@ namespace mwmp // If we've received a request for information, comply with it if (event.action == mwmp::BaseEvent::REQUEST) - event.sendCellContainers(ptrCellStore); + { + if (event.worldObjectCount == 0) + { + LOG_APPEND(Log::LOG_VERBOSE, "- Request had no objects attached, so we are sending all containers in the cell %s", + event.cell.getDescription().c_str()); + event.reset(); + event.cell = *ptrCellStore->getCell(); + event.action = event.action == mwmp::BaseEvent::SET; + event.addAllContainers(ptrCellStore); + event.sendContainer(); + } + else + { + LOG_APPEND(Log::LOG_VERBOSE, "- Request was for %i %s", event.worldObjectCount, event.worldObjectCount == 1 ? "object" : "objects"); + std::vector requestObjects = event.worldObjects; + event.reset(); + event.cell = *ptrCellStore->getCell(); + event.action = event.action == mwmp::BaseEvent::SET; + event.addRequestedContainers(ptrCellStore, requestObjects); + + if (event.worldObjects.size() > 0) + event.sendContainer(); + } + } // Otherwise, edit containers based on the information received else + { + LOG_APPEND(Log::LOG_VERBOSE, "- Editing container contents to match those of packet", event.worldObjectCount); event.editContainers(ptrCellStore); + } } };