[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.
pull/399/head
David Cernat 7 years ago
parent ec1311fcb7
commit f80f3bd484

@ -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<ESM::Container> *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<WorldObject>& 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<ESM::Container> *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();

@ -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<WorldObject>& 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();

@ -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<WorldObject> 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);
}
}
};

Loading…
Cancel
Save