From ecf00af54822f05a7f7f48c4c7e0332e041dc81e Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 4 Dec 2019 16:43:56 +0200 Subject: [PATCH] [General] Implement WorldDestinationOverride packet, part 1 Destinations for doors with cell transitions are now overridden. --- .../openmw-mp/Script/Functions/Worldstate.cpp | 26 ++++++++++ .../openmw-mp/Script/Functions/Worldstate.hpp | 33 ++++++++++++ apps/openmw/CMakeLists.txt | 4 +- apps/openmw/mwclass/door.cpp | 29 ++++++++++- .../mwmp/processors/ProcessorInitializer.cpp | 4 +- .../ProcessorWorldDestinationOverride.hpp | 33 ++++++++++++ components/CMakeLists.txt | 3 +- components/openmw-mp/Base/BaseWorldstate.hpp | 2 + .../WorldstatePacketController.cpp | 2 + components/openmw-mp/NetworkMessages.hpp | 1 + .../PacketWorldDestinationOverride.cpp | 52 +++++++++++++++++++ .../PacketWorldDestinationOverride.hpp | 17 ++++++ 12 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 apps/openmw/mwmp/processors/worldstate/ProcessorWorldDestinationOverride.hpp create mode 100644 components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.cpp create mode 100644 components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.hpp diff --git a/apps/openmw-mp/Script/Functions/Worldstate.cpp b/apps/openmw-mp/Script/Functions/Worldstate.cpp index 6423275df..9b054f45f 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.cpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.cpp @@ -197,6 +197,11 @@ void WorldstateFunctions::AddEnforcedCollisionRefId(const char *refId) noexcept writeWorldstate.enforcedCollisionRefIds.push_back(refId); } +void WorldstateFunctions::AddDestinationOverride(const char *oldCellDescription, const char *newCellDescription) noexcept +{ + writeWorldstate.destinationOverrides[oldCellDescription] = newCellDescription; +} + void WorldstateFunctions::ClearSynchronizedClientScriptIds() noexcept { writeWorldstate.synchronizedClientScriptIds.clear(); @@ -212,6 +217,11 @@ void WorldstateFunctions::ClearEnforcedCollisionRefIds() noexcept writeWorldstate.enforcedCollisionRefIds.clear(); } +void WorldstateFunctions::ClearDestinationOverrides() noexcept +{ + writeWorldstate.destinationOverrides.clear(); +} + void WorldstateFunctions::SaveMapTileImageFile(unsigned int index, const char *filePath) noexcept { if (index >= readWorldstate->mapTiles.size()) @@ -342,6 +352,22 @@ void WorldstateFunctions::SendWorldCollisionOverride(unsigned short pid, bool se packet->Send(true); } +void WorldstateFunctions::SendWorldDestinationOverride(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + writeWorldstate.guid = player->guid; + + mwmp::WorldstatePacket *packet = mwmp::Networking::get().getWorldstatePacketController()->GetPacket(ID_WORLD_DESTINATION_OVERRIDE); + packet->setWorldstate(&writeWorldstate); + + if (!skipAttachedPlayer) + packet->Send(false); + if (sendToOtherPlayers) + packet->Send(true); +} + void WorldstateFunctions::SendWorldRegionAuthority(unsigned short pid) noexcept { Player *player; diff --git a/apps/openmw-mp/Script/Functions/Worldstate.hpp b/apps/openmw-mp/Script/Functions/Worldstate.hpp index d0d35b073..1c330836f 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.hpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.hpp @@ -52,10 +52,12 @@ {"AddSynchronizedClientScriptId", WorldstateFunctions::AddSynchronizedClientScriptId},\ {"AddSynchronizedClientGlobalId", WorldstateFunctions::AddSynchronizedClientGlobalId},\ {"AddEnforcedCollisionRefId", WorldstateFunctions::AddEnforcedCollisionRefId},\ + {"AddDestinationOverride", WorldstateFunctions::AddDestinationOverride},\ \ {"ClearSynchronizedClientScriptIds", WorldstateFunctions::ClearSynchronizedClientScriptIds},\ {"ClearSynchronizedClientGlobalIds", WorldstateFunctions::ClearSynchronizedClientGlobalIds},\ {"ClearEnforcedCollisionRefIds", WorldstateFunctions::ClearEnforcedCollisionRefIds},\ + {"ClearDestinationOverrides", WorldstateFunctions::ClearDestinationOverrides},\ \ {"SaveMapTileImageFile", WorldstateFunctions::SaveMapTileImageFile},\ {"LoadMapTileImageFile", WorldstateFunctions::LoadMapTileImageFile},\ @@ -66,6 +68,7 @@ {"SendWorldTime", WorldstateFunctions::SendWorldTime},\ {"SendWorldWeather", WorldstateFunctions::SendWorldWeather},\ {"SendWorldCollisionOverride", WorldstateFunctions::SendWorldCollisionOverride},\ + {"SendWorldDestinationOverride", WorldstateFunctions::SendWorldDestinationOverride},\ {"SendWorldRegionAuthority", WorldstateFunctions::SendWorldRegionAuthority},\ \ {"ReadLastWorldstate", WorldstateFunctions::ReadLastWorldstate},\ @@ -374,6 +377,16 @@ public: */ static void AddEnforcedCollisionRefId(const char* refId) noexcept; + /** + * \brief Add a destination override containing the cell description for the old cell + * and the new cell. + * + * \param oldCellDescription The old cell description. + * \param newCellDescription The new cell description. + * \return void + */ + static void AddDestinationOverride(const char* oldCellDescription, const char* newCellDescription) noexcept; + /** * \brief Clear the list of script IDs whose variable changes should be sent to the * the server by clients. @@ -398,6 +411,13 @@ public: */ static void ClearEnforcedCollisionRefIds() noexcept; + /** + * \brief Clear the list of destination overrides. + * + * \return void + */ + static void ClearDestinationOverrides() noexcept; + /** * \brief Save the .png image data of the map tile at a certain index in the read worldstate's * map changes. @@ -505,6 +525,19 @@ public: */ static void SendWorldCollisionOverride(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept; + /** + * \brief Send a WorldDestinationOverride packet with the current destination overrides in + * the write-only worldstate. + * + * \param pid The player ID attached to the packet. + * \param sendToOtherPlayers Whether this packet should be sent to players other than the + * player attached to the packet (false by default). + * \param skipAttachedPlayer Whether the packet should skip being sent to the player attached + * to the packet (false by default). + * \return void + */ + static void SendWorldDestinationOverride(unsigned short pid, bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept; + // All methods below are deprecated versions of methods from above diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 20bcbc0a3..2f8a6f593 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -138,8 +138,8 @@ add_openmw_dir (mwmp/processors/object BaseObjectProcessor ) add_openmw_dir (mwmp/processors/worldstate ProcessorCellReset ProcessorClientScriptSettings ProcessorRecordDynamic - ProcessorWorldCollisionOverride ProcessorWorldKillCount ProcessorWorldMap ProcessorWorldRegionAuthority ProcessorWorldTime - ProcessorWorldWeather + ProcessorWorldCollisionOverride ProcessorWorldDestinationOverride ProcessorWorldKillCount ProcessorWorldMap + ProcessorWorldRegionAuthority ProcessorWorldTime ProcessorWorldWeather ) # Main executable diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index ce35a1af3..ecb8ea401 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -257,7 +257,22 @@ namespace MWClass } else { - std::shared_ptr action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true)); + /* + Start of tes3mp change (major) + + If there is a destination override in the mwmp::Worldstate for this door's original + destination, use it + */ + std::string destinationCell = ptr.getCellRef().getDestCell(); + + if (mwmp::Main::get().getNetworking()->getWorldstate()->destinationOverrides.count(destinationCell) != 0) + destinationCell = mwmp::Main::get().getNetworking()->getWorldstate()->destinationOverrides[destinationCell]; + + std::shared_ptr action(new MWWorld::ActionTeleport(destinationCell, ptr.getCellRef().getDoorDest(), true)); + /* + End of tes3mp change (major) + */ + action->setSound(openSound); return action; } @@ -374,6 +389,18 @@ namespace MWClass { // door leads to an interior, use interior name as tooltip dest = door.mRef.getDestCell(); + + /* + Start of tes3mp change (major) + + If there is a destination override in the mwmp::Worldstate for this door's original + destination, use it + */ + if (mwmp::Main::get().getNetworking()->getWorldstate()->destinationOverrides.count(dest) != 0) + dest = mwmp::Main::get().getNetworking()->getWorldstate()->destinationOverrides[dest]; + /* + End of tes3mp change (major) + */ } else { diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 2ff22cfa7..7cacfe516 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -95,6 +95,7 @@ #include "worldstate/ProcessorClientScriptSettings.hpp" #include "worldstate/ProcessorRecordDynamic.hpp" #include "worldstate/ProcessorWorldCollisionOverride.hpp" +#include "worldstate/ProcessorWorldDestinationOverride.hpp" #include "worldstate/ProcessorWorldKillCount.hpp" #include "worldstate/ProcessorWorldMap.hpp" #include "worldstate/ProcessorWorldRegionAuthority.hpp" @@ -191,11 +192,12 @@ void ProcessorInitializer() ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic()); ActorProcessor::AddProcessor(new ProcessorActorTest()); - WorldstateProcessor::AddProcessor(new ProcessorWorldKillCount()); WorldstateProcessor::AddProcessor(new ProcessorCellReset()); WorldstateProcessor::AddProcessor(new ProcessorClientScriptSettings()); WorldstateProcessor::AddProcessor(new ProcessorRecordDynamic()); WorldstateProcessor::AddProcessor(new ProcessorWorldCollisionOverride()); + WorldstateProcessor::AddProcessor(new ProcessorWorldDestinationOverride()); + WorldstateProcessor::AddProcessor(new ProcessorWorldKillCount()); WorldstateProcessor::AddProcessor(new ProcessorWorldMap()); WorldstateProcessor::AddProcessor(new ProcessorWorldRegionAuthority()); WorldstateProcessor::AddProcessor(new ProcessorWorldTime()); diff --git a/apps/openmw/mwmp/processors/worldstate/ProcessorWorldDestinationOverride.hpp b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldDestinationOverride.hpp new file mode 100644 index 000000000..6bf3c603f --- /dev/null +++ b/apps/openmw/mwmp/processors/worldstate/ProcessorWorldDestinationOverride.hpp @@ -0,0 +1,33 @@ +#ifndef OPENMW_PROCESSORWORLDDESTINATIONOVERRIDE_HPP +#define OPENMW_PROCESSORWORLDDESTINATIONOVERRIDE_HPP + + +#include +#include +#include "../WorldstateProcessor.hpp" + +namespace mwmp +{ + class ProcessorWorldDestinationOverride final: public WorldstateProcessor + { + public: + ProcessorWorldDestinationOverride() + { + BPP_INIT(ID_WORLD_DESTINATION_OVERRIDE) + } + + virtual void Do(WorldstatePacket &packet, Worldstate &worldstate) + { + LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Received ID_WORLD_DESTINATION_OVERRIDE with the following overrides:"); + + for (auto iterator : worldstate.destinationOverrides) + { + LOG_APPEND(TimedLog::LOG_INFO, "- %s now leads to %s", iterator.first.c_str(), iterator.second.c_str()); + } + } + }; +} + + + +#endif //OPENMW_PROCESSORWORLDDESTINATIONOVERRIDE_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 050daa63d..86b32d0c6 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -217,7 +217,8 @@ add_component_dir (openmw-mp/Packets/Worldstate WorldstatePacket PacketCellCreate PacketCellReset PacketClientScriptSettings PacketRecordDynamic PacketWorldCollisionOverride - PacketWorldKillCount PacketWorldMap PacketWorldRegionAuthority PacketWorldTime PacketWorldWeather + PacketWorldDestinationOverride PacketWorldKillCount PacketWorldMap PacketWorldRegionAuthority PacketWorldTime + PacketWorldWeather ) add_component_dir (fallback diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index c2ba356b3..9a19c8208 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_BASEWORLDSTATE_HPP #define OPENMW_BASEWORLDSTATE_HPP +#include #include #include @@ -359,6 +360,7 @@ namespace mwmp std::vector killChanges; std::vector enforcedCollisionRefIds; + std::map destinationOverrides; std::vector mapTiles; diff --git a/components/openmw-mp/Controllers/WorldstatePacketController.cpp b/components/openmw-mp/Controllers/WorldstatePacketController.cpp index bcfce8e1b..2002bca59 100644 --- a/components/openmw-mp/Controllers/WorldstatePacketController.cpp +++ b/components/openmw-mp/Controllers/WorldstatePacketController.cpp @@ -2,6 +2,7 @@ #include "../Packets/Worldstate/PacketClientScriptSettings.hpp" #include "../Packets/Worldstate/PacketRecordDynamic.hpp" #include "../Packets/Worldstate/PacketWorldCollisionOverride.hpp" +#include "../Packets/Worldstate/PacketWorldDestinationOverride.hpp" #include "../Packets/Worldstate/PacketWorldKillCount.hpp" #include "../Packets/Worldstate/PacketWorldMap.hpp" #include "../Packets/Worldstate/PacketWorldRegionAuthority.hpp" @@ -24,6 +25,7 @@ mwmp::WorldstatePacketController::WorldstatePacketController(RakNet::RakPeerInte AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); + AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); AddPacket(&packets, peer); diff --git a/components/openmw-mp/NetworkMessages.hpp b/components/openmw-mp/NetworkMessages.hpp index 5ba9ba322..4916dba0c 100644 --- a/components/openmw-mp/NetworkMessages.hpp +++ b/components/openmw-mp/NetworkMessages.hpp @@ -110,6 +110,7 @@ enum GameMessages ID_PLAYER_ITEM_USE, ID_PLAYER_CAST, ID_PLAYER_TEAM, + ID_WORLD_DESTINATION_OVERRIDE, ID_PLACEHOLDER }; diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.cpp b/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.cpp new file mode 100644 index 000000000..d8ec3c462 --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.cpp @@ -0,0 +1,52 @@ +#include "PacketWorldDestinationOverride.hpp" +#include + +#include + +using namespace mwmp; + +PacketWorldDestinationOverride::PacketWorldDestinationOverride(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer) +{ + packetID = ID_WORLD_DESTINATION_OVERRIDE; + orderChannel = CHANNEL_WORLDSTATE; +} + +void PacketWorldDestinationOverride::Packet(RakNet::BitStream *newBitstream, bool send) +{ + WorldstatePacket::Packet(newBitstream, send); + + uint32_t destinationCount; + + if (send) + destinationCount = static_cast(worldstate->destinationOverrides.size()); + + RW(destinationCount, send); + + if (!send) + { + worldstate->destinationOverrides.clear(); + } + + std::string mapIndex; + std::string mapValue; + + if (send) + { + for (auto &&destinationOverride : worldstate->destinationOverrides) + { + mapIndex = destinationOverride.first; + mapValue = destinationOverride.second; + RW(mapIndex, send, false); + RW(mapValue, send, false); + } + } + else + { + for (unsigned int n = 0; n < destinationCount; n++) + { + RW(mapIndex, send, false); + RW(mapValue, send, false); + worldstate->destinationOverrides[mapIndex] = mapValue; + } + } +} diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.hpp b/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.hpp new file mode 100644 index 000000000..e8e0d819d --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldDestinationOverride.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_PACKETWORLDDESTINATIONOVERRIDE_HPP +#define OPENMW_PACKETWORLDDESTINATIONOVERRIDE_HPP + +#include + +namespace mwmp +{ + class PacketWorldDestinationOverride : public WorldstatePacket + { + public: + PacketWorldDestinationOverride(RakNet::RakPeerInterface *peer); + + virtual void Packet(RakNet::BitStream *newBitstream, bool send); + }; +} + +#endif //OPENMW_PACKETWORLDDESTINATIONOVERRIDE_HPP