diff --git a/client/adventureMap/AdventureMapInterface.cpp b/client/adventureMap/AdventureMapInterface.cpp index c9b9e28da..8aa0de501 100644 --- a/client/adventureMap/AdventureMapInterface.cpp +++ b/client/adventureMap/AdventureMapInterface.cpp @@ -441,12 +441,10 @@ void AdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID) if(auto iw = GH.windows().topWindow()) iw->close(); - boost::thread newThread([this]() - { - hotkeyEndingTurn(); - }); - - newThread.detach(); + GH.dispatchMainThread([this]() + { + hotkeyEndingTurn(); + }); } } diff --git a/lib/mapping/MapReaderH3M.cpp b/lib/mapping/MapReaderH3M.cpp index 4fb3917d2..4a1c75e49 100644 --- a/lib/mapping/MapReaderH3M.cpp +++ b/lib/mapping/MapReaderH3M.cpp @@ -83,7 +83,10 @@ ArtifactID MapReaderH3M::readArtifact() ArtifactID MapReaderH3M::readArtifact8() { - ArtifactID result(reader->readInt8()); + ArtifactID result(reader->readUInt8()); + + if(result.getNum() == 0xff) + return ArtifactID::NONE; if (result.getNum() < features.artifactsCount) return remapIdentifier(result); diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index a713b5bdc..46d4f564b 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -40,19 +40,11 @@ bool CPathfinderHelper::canMoveFromNode(const PathNodeInfo & source) const if (source.node->isTeleportAction()) return true; - // we can go through garrisons - if (source.nodeObject->ID == MapObjectID::GARRISON || source.nodeObject->ID == MapObjectID::GARRISON2) - return true; + // we can not go through teleporters since moving onto a teleport will teleport hero and may invalidate path (e.g. one-way teleport or enemy hero on other side) + if (dynamic_cast(source.nodeObject) != nullptr) + return false; - // or through border gate (if we stand on it then we already have the key) - if (source.nodeObject->ID == MapObjectID::BORDER_GATE) - return true; - - // or "through" boat, but only if this is embarking - if (source.nodeObject->ID == MapObjectID::BOAT && source.node->action == EPathNodeAction::EMBARK) - return true; - - return false; + return true; } std::vector CPathfinderHelper::getNeighbourTiles(const PathNodeInfo & source) const diff --git a/lib/serializer/Connection.cpp b/lib/serializer/Connection.cpp index c4c98f4f6..de5f3b85d 100644 --- a/lib/serializer/Connection.cpp +++ b/lib/serializer/Connection.cpp @@ -221,6 +221,8 @@ int CConnection::read(void * data, unsigned size) CConnection::~CConnection() { + close(); + if(handler) { // ugly workaround to avoid self-join if last strong reference to shared_ptr that owns this class has been released in this very thread, e.g. on netpack processing @@ -229,8 +231,6 @@ CConnection::~CConnection() else handler->detach(); } - - close(); } template @@ -246,6 +246,15 @@ void CConnection::close() { if(socket) { + try + { + socket->shutdown(boost::asio::ip::tcp::socket::shutdown_receive); + } + catch (const boost::system::system_error & e) + { + logNetwork->error("error closing socket: %s", e.what()); + } + socket->close(); socket.reset(); } diff --git a/server/processors/TurnOrderProcessor.cpp b/server/processors/TurnOrderProcessor.cpp index 87a63cb92..db3969124 100644 --- a/server/processors/TurnOrderProcessor.cpp +++ b/server/processors/TurnOrderProcessor.cpp @@ -263,8 +263,6 @@ void TurnOrderProcessor::onPlayerEndsGame(PlayerColor which) if (actingPlayers.empty()) doStartNewDay(); - - assert(!actingPlayers.empty()); } bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)