From 29be79e852b1b48b6f659876b8f1644890a4e9c3 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 19 Jun 2018 00:37:52 +0300 Subject: [PATCH 1/5] [General] Switch RakNet enums to CrabNet enums CrabNet is TES3MP's fork of RakNet that has deviated too far from RakNet to still be compatible with it. --- apps/openmw-mp/Networking.cpp | 2 +- apps/openmw-mp/main.cpp | 4 ++-- apps/openmw/mwmp/Networking.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw-mp/Networking.cpp b/apps/openmw-mp/Networking.cpp index 7a0339c81..57e44c628 100644 --- a/apps/openmw-mp/Networking.cpp +++ b/apps/openmw-mp/Networking.cpp @@ -292,7 +292,7 @@ void Networking::newPlayer(RakNet::RakNetGUID guid) if (pl->first == guid) continue; // If an invalid key makes it into the Players map, ignore it - else if (pl->first == RakNet::UNASSIGNED_RAKNET_GUID) continue; + else if (pl->first == RakNet::UNASSIGNED_CRABNET_GUID) continue; // if player not fully connected else if (pl->second == nullptr) continue; diff --git a/apps/openmw-mp/main.cpp b/apps/openmw-mp/main.cpp index f9c490a08..1e69f6542 100644 --- a/apps/openmw-mp/main.cpp +++ b/apps/openmw-mp/main.cpp @@ -239,9 +239,9 @@ int main(int argc, char *argv[]) switch (peer->Startup((unsigned) players, &sd, 1)) { - case RakNet::RAKNET_STARTED: + case RakNet::CRABNET_STARTED: break; - case RakNet::RAKNET_ALREADY_STARTED: + case RakNet::CRABNET_ALREADY_STARTED: throw runtime_error("Already started"); case RakNet::INVALID_SOCKET_DESCRIPTORS: throw runtime_error("Incorrect port or address"); diff --git a/apps/openmw/mwmp/Networking.cpp b/apps/openmw/mwmp/Networking.cpp index b4714a922..7e4bc8d30 100644 --- a/apps/openmw/mwmp/Networking.cpp +++ b/apps/openmw/mwmp/Networking.cpp @@ -203,7 +203,7 @@ Networking::Networking(): peer(RakNet::RakPeerInterface::GetInstance()), playerP RakNet::SocketDescriptor sd; sd.port=0; auto b = peer->Startup(1, &sd, 1); - RakAssert(b==RakNet::RAKNET_STARTED); + RakAssert(b==RakNet::CRABNET_STARTED); playerPacketController.SetStream(0, &bsOut); actorPacketController.SetStream(0, &bsOut); From 5b461b09ca29c9b311e367f4dc8c1bd65d0e6d07 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 19 Jun 2018 05:24:26 +0300 Subject: [PATCH 2/5] [Client] Display error when receiving ID_INCOMPATIBLE_PROTOCOL_VERSION --- apps/openmw/mwmp/Networking.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/openmw/mwmp/Networking.cpp b/apps/openmw/mwmp/Networking.cpp index 7e4bc8d30..3b54f15ff 100644 --- a/apps/openmw/mwmp/Networking.cpp +++ b/apps/openmw/mwmp/Networking.cpp @@ -305,6 +305,13 @@ void Networking::connect(const std::string &ip, unsigned short port, std::vector queue = false; break; } + case ID_INCOMPATIBLE_PROTOCOL_VERSION: + { + errmsg = "Network protocol mismatch!\nMake sure your client is really on the same version\n" + "as the server you are trying to connect to."; + queue = false; + break; + } case ID_CONNECTION_REQUEST_ACCEPTED: { serverAddr = packet->systemAddress; From c3c7f2c8f9c4bc1eb0f0921ad6177a016c2ce50d Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 20 Jun 2018 02:00:12 +0300 Subject: [PATCH 3/5] [Server] Don't automatically synchronize ObjectDelete packets --- apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp b/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp index 2487762ee..929205eec 100644 --- a/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp +++ b/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp @@ -16,8 +16,6 @@ namespace mwmp void Do(ObjectPacket &packet, Player &player, BaseObjectList &objectList) override { LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received %s from %s", strPacketID.c_str(), player.npc.mName.c_str()); - - packet.Send(true); Script::Call(player.getId(), objectList.cell.getDescription().c_str()); } From fd05beef9453421fd05a174765b11c86956e1df7 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Wed, 20 Jun 2018 02:01:19 +0300 Subject: [PATCH 4/5] [Client] Don't delete disposed of corpses on client Clients should instead await a server reply approving the deletion. --- apps/openmw/mwgui/container.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index d4614b5ac..f13184527 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -372,13 +372,16 @@ namespace MWGui if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) { onTakeAllButtonClicked(mTakeButton); - + + if (mPtr.getClass().isPersistent(mPtr)) + MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); /* - Start of tes3mp addition + Start of tes3mp change (major) - Send an ID_OBJECT_DELETE packet every time a corpse is disposed of + Instead of deleting the corpse on this client, simply send an ID_OBJECT_DELETE + packet to the server as a request for the deletion */ - if (!mPtr.getClass().isPersistent(mPtr)) + else { mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); objectList->reset(); @@ -386,14 +389,9 @@ namespace MWGui objectList->sendObjectDelete(); } /* - End of tes3mp addition + End of tes3mp change (major) */ - if (mPtr.getClass().isPersistent(mPtr)) - MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); - else - MWBase::Environment::get().getWorld()->deleteObject(mPtr); - mPtr = MWWorld::Ptr(); } } From 7e90d1f2a47f904cd7f51a1f200908b27a6f9d72 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Thu, 21 Jun 2018 16:44:49 +0300 Subject: [PATCH 5/5] [Client] Fix interior-to-exterior and v.v. cell transitions for actors Make sure only players who are cell authorities can get actors to teleport across cells for them, and display a message box for players who are not cell authorities. --- apps/openmw/mwmp/CellController.cpp | 8 ++++---- apps/openmw/mwworld/actionteleport.cpp | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index b1f118db5..f66f77d3e 100644 --- a/apps/openmw/mwmp/CellController.cpp +++ b/apps/openmw/mwmp/CellController.cpp @@ -204,14 +204,14 @@ bool CellController::isLocalActor(MWWorld::Ptr ptr) std::string actorIndex = generateMapIndex(ptr); - return (localActorsToCells.count(actorIndex) > 0 && isInitializedCell(localActorsToCells.at(actorIndex))); + return localActorsToCells.count(actorIndex) > 0; } bool CellController::isLocalActor(int refNumIndex, int mpNum) { std::string actorIndex = generateMapIndex(refNumIndex, mpNum); - return (localActorsToCells.count(actorIndex) > 0 && isInitializedCell(localActorsToCells.at(actorIndex))); + return localActorsToCells.count(actorIndex) > 0; } LocalActor *CellController::getLocalActor(MWWorld::Ptr ptr) @@ -247,14 +247,14 @@ bool CellController::isDedicatedActor(MWWorld::Ptr ptr) std::string actorIndex = generateMapIndex(ptr); - return (dedicatedActorsToCells.count(actorIndex) > 0 && isInitializedCell(dedicatedActorsToCells.at(actorIndex))); + return dedicatedActorsToCells.count(actorIndex) > 0; } bool CellController::isDedicatedActor(int refNumIndex, int mpNum) { std::string actorIndex = generateMapIndex(refNumIndex, mpNum); - return (dedicatedActorsToCells.count(actorIndex) > 0 && isInitializedCell(dedicatedActorsToCells.at(actorIndex))); + return dedicatedActorsToCells.count(actorIndex) > 0; } DedicatedActor *CellController::getDedicatedActor(MWWorld::Ptr ptr) diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 0d5f642d6..f69dd3415 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -5,6 +5,8 @@ Include additional headers for multiplayer purposes */ +#include +#include "../mwbase/windowmanager.hpp" #include "../mwmp/Main.hpp" #include "../mwmp/CellController.hpp" /* @@ -46,7 +48,7 @@ namespace MWWorld Update LocalActors before we unload their cells, so packets with their cell changes can be sent */ - mwmp::Main::get().getCellController()->updateLocal(false); + mwmp::Main::get().getCellController()->updateLocal(true); /* End of tes3mp addition */ @@ -69,6 +71,25 @@ namespace MWWorld } else { + /* + Start of tes3mp change (major) + + Only allow LocalActors to teleport across cells + */ + if (!mwmp::Main::get().getCellController()->isLocalActor(actor)) + { + MWBase::Environment::get().getWindowManager()->messageBox("That NPC can't follow you because their AI is running on another player's client."); + return; + } + else + { + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Teleporting actor %s-%i-%i to new cell", actor.getCellRef().getRefId().c_str(), + actor.getCellRef().getRefNum().mIndex, actor.getCellRef().getMpNum()); + } + /* + End of tes3mp change (major) + */ + if (mCellName.empty()) { int cellX;