diff --git a/apps/openmw-mp/Networking.cpp b/apps/openmw-mp/Networking.cpp index 00a6bd875..ad890ce22 100644 --- a/apps/openmw-mp/Networking.cpp +++ b/apps/openmw-mp/Networking.cpp @@ -313,7 +313,7 @@ void Networking::newPlayer(RakNet::RakNetGUID guid) if (pl->guid == guid) return; // If an invalid key makes it into the Players map, ignore it - else if (pl->guid == RakNet::UNASSIGNED_RAKNET_GUID) return; + else if (pl->guid == RakNet::UNASSIGNED_CRABNET_GUID) return; // If we are iterating over a player who has inputted their name, proceed else if (pl->getLoadState() == Player::POSTLOADED) diff --git a/apps/openmw-mp/main.cpp b/apps/openmw-mp/main.cpp index 6d8bf6415..1bc1ae1c7 100644 --- a/apps/openmw-mp/main.cpp +++ b/apps/openmw-mp/main.cpp @@ -235,9 +235,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: Utils::throwError("Already started"); break; case RakNet::INVALID_SOCKET_DESCRIPTORS: diff --git a/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp b/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp index 5545ce4fa..20c8fb8c9 100644 --- a/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp +++ b/apps/openmw-mp/processors/object/ProcessorObjectDelete.hpp @@ -16,15 +16,11 @@ namespace mwmp void Do(ObjectPacket &packet, const std::shared_ptr &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); auto objCtrl = Networking::get().getState().getObjectCtrl(); auto objects = objCtrl.copyObjects(objectList); Networking::get().getState().getEventCtrl().Call(player.get(), objects); - - objCtrl.sendObjects(player, objects, objectList.cell); } }; } diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 8f7a301b8..6cd155a0e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -373,13 +373,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(); @@ -387,14 +390,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(); } } diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index d89866a2c..8237fa4bb 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/mwmp/Networking.cpp b/apps/openmw/mwmp/Networking.cpp index 73e0ee5bc..a8b5f1bf5 100644 --- a/apps/openmw/mwmp/Networking.cpp +++ b/apps/openmw/mwmp/Networking.cpp @@ -201,7 +201,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); @@ -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; 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; diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp b/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp new file mode 100644 index 000000000..36b5c4303 --- /dev/null +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp @@ -0,0 +1,52 @@ +#include +#include "PacketWorldMap.hpp" + +using namespace std; +using namespace mwmp; + +PacketWorldMap::PacketWorldMap(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer) +{ + packetID = ID_WORLD_MAP; +} + +void PacketWorldMap::Packet(RakNet::BitStream *bs, bool send) +{ + WorldstatePacket::Packet(bs, send); + + uint32_t changesCount; + + if (send) + changesCount = static_cast(worldstate->mapChanges.mapTiles.size()); + + RW(changesCount, send); + + if (!send) + { + worldstate->mapChanges.mapTiles.clear(); + worldstate->mapChanges.mapTiles.resize(changesCount); + } + + for (auto &&mapTile : worldstate->mapChanges.mapTiles) + { + RW(mapTile.x, send); + RW(mapTile.y, send); + + uint32_t imageDataCount; + + if (send) + imageDataCount = static_cast(mapTile.imageData.size()); + + RW(imageDataCount, send); + + if (!send) + { + mapTile.imageData.clear(); + mapTile.imageData.resize(imageDataCount); + } + + for (auto &&imageChar : mapTile.imageData) + { + RW(imageChar, send); + } + } +}