diff --git a/src/blackcore/fsd/fsdclient.cpp b/src/blackcore/fsd/fsdclient.cpp index 389e49ed0..d51ff929b 100644 --- a/src/blackcore/fsd/fsdclient.cpp +++ b/src/blackcore/fsd/fsdclient.cpp @@ -31,6 +31,7 @@ #include "blackcore/fsd/servererror.h" #include "blackcore/fsd/interimpilotdataupdate.h" #include "blackcore/fsd/visualpilotdataupdate.h" +#include "blackcore/fsd/visualpilotdatatoggle.h" #include "blackcore/fsd/planeinforequest.h" #include "blackcore/fsd/planeinformation.h" #include "blackcore/fsd/planeinforequestfsinn.h" @@ -50,6 +51,7 @@ #include #include #include +#include using namespace BlackConfig; using namespace BlackCore::Vatsim; @@ -116,7 +118,7 @@ namespace BlackCore::Fsd connect(&m_interimPositionUpdateTimer, &QTimer::timeout, this, &CFSDClient::sendInterimPilotDataUpdate); m_visualPositionUpdateTimer.setObjectName(this->objectName().append(":m_visualPositionUpdateTimer")); - connect(&m_visualPositionUpdateTimer, &QTimer::timeout, this, &CFSDClient::sendVisualPilotDataUpdate); + connect(&m_visualPositionUpdateTimer, &QTimer::timeout, this, [this] { sendVisualPilotDataUpdate(); }); m_scheduledConfigUpdate.setObjectName(this->objectName().append(":m_scheduledConfigUpdate")); connect(&m_scheduledConfigUpdate, &QTimer::timeout, this, &CFSDClient::sendIncrementalAircraftConfig); @@ -361,6 +363,11 @@ namespace BlackCore::Fsd myAircraft.getParts().isOnGround()); sendQueudedMessage(pilotDataUpdate); } + + if (this->isVisualPositionSendingEnabledForServer()) + { + sendVisualPilotDataUpdate(true); + } } void CFSDClient::sendInterimPilotDataUpdate() @@ -386,28 +393,35 @@ namespace BlackCore::Fsd } } - void CFSDClient::sendVisualPilotDataUpdate() + void CFSDClient::sendVisualPilotDataUpdate(bool slowUpdate) { if (this->getConnectionStatus().isDisconnected() && ! m_unitTestMode) { return; } if (m_loginMode == CLoginMode::Observer || !isVisualPositionSendingEnabledForServer()) { return; } const CSimulatedAircraft myAircraft(getOwnAircraft()); - static constexpr double minVelocity = 0.00005; - if (std::abs(myAircraft.getVelocity().getVelocityX(CSpeedUnit::m_s())) < minVelocity && - std::abs(myAircraft.getVelocity().getVelocityY(CSpeedUnit::m_s())) < minVelocity && - std::abs(myAircraft.getVelocity().getVelocityZ(CSpeedUnit::m_s())) < minVelocity && - std::abs(myAircraft.getVelocity().getPitchVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity && - std::abs(myAircraft.getVelocity().getRollVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity && - std::abs(myAircraft.getVelocity().getHeadingVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity) + if (!slowUpdate) { - if (m_stoppedSendingVisualPositions) { return; } - m_stoppedSendingVisualPositions = true; - } - else - { - m_stoppedSendingVisualPositions = false; - } + static constexpr double minVelocity = 0.00005; + if (std::abs(myAircraft.getVelocity().getVelocityX(CSpeedUnit::m_s())) < minVelocity && + std::abs(myAircraft.getVelocity().getVelocityY(CSpeedUnit::m_s())) < minVelocity && + std::abs(myAircraft.getVelocity().getVelocityZ(CSpeedUnit::m_s())) < minVelocity && + std::abs(myAircraft.getVelocity().getPitchVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity && + std::abs(myAircraft.getVelocity().getRollVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity && + std::abs(myAircraft.getVelocity().getHeadingVelocity(CAngleUnit::rad(), CTimeUnit::s())) < minVelocity) + { + if (m_stoppedSendingVisualPositions) { return; } + m_stoppedSendingVisualPositions = true; + } + else + { + m_stoppedSendingVisualPositions = false; + } + if (!m_serverWantsVisualPositions) + { + return; + } + } VisualPilotDataUpdate visualPilotDataUpdate(getOwnCallsignAsString(), myAircraft.latitude().value(CAngleUnit::deg()), myAircraft.longitude().value(CAngleUnit::deg()), @@ -1062,6 +1076,7 @@ namespace BlackCore::Fsd m_messageTypeMapping["$!!"] = MessageType::KillRequest; m_messageTypeMapping["@"] = MessageType::PilotDataUpdate; m_messageTypeMapping["^"] = MessageType::VisualPilotDataUpdate; + m_messageTypeMapping["$SF"] = MessageType::VisualPilotDataToggle; m_messageTypeMapping["$PI"] = MessageType::Ping; m_messageTypeMapping["$PO"] = MessageType::Pong; m_messageTypeMapping["$ER"] = MessageType::ServerError; @@ -1286,6 +1301,12 @@ namespace BlackCore::Fsd emit visualPilotDataUpdateReceived(situation); } + void CFSDClient::handleVisualPilotDataToggle(const QStringList& tokens) + { + const VisualPilotDataToggle toggle = VisualPilotDataToggle::fromTokens(tokens); + m_serverWantsVisualPositions = toggle.m_active; + } + void CFSDClient::handlePing(const QStringList &tokens) { const Ping ping = Ping::fromTokens(tokens); @@ -1852,6 +1873,7 @@ namespace BlackCore::Fsd void CFSDClient::clearState() { m_stoppedSendingVisualPositions = false; + m_serverWantsVisualPositions = false; m_textMessagesToConsolidate.clear(); m_pendingAtisQueries.clear(); m_lastPositionUpdate.clear(); @@ -2204,6 +2226,7 @@ namespace BlackCore::Fsd case MessageType::PilotClientCom: handleCustomPilotPacket(tokens); break; case MessageType::RevBClientParts: handleRevBClientPartsPacket(tokens); break; case MessageType::VisualPilotDataUpdate: handleVisualPilotDataUpdate(tokens); break; + case MessageType::VisualPilotDataToggle: handleVisualPilotDataToggle(tokens); break; case MessageType::EuroscopeSimData: handleEuroscopeSimData(tokens); break; // normally we should not get here diff --git a/src/blackcore/fsd/fsdclient.h b/src/blackcore/fsd/fsdclient.h index 15b7936a4..55abc7e8b 100644 --- a/src/blackcore/fsd/fsdclient.h +++ b/src/blackcore/fsd/fsdclient.h @@ -262,7 +262,7 @@ namespace BlackCore::Fsd void sendDeleteAtc(); void sendPilotDataUpdate(); void sendInterimPilotDataUpdate(); - void sendVisualPilotDataUpdate(); + void sendVisualPilotDataUpdate(bool slowUpdate = false); void sendAtcDataUpdate(double latitude, double longitude); void sendPing(const QString &receiver); // @@ -366,6 +366,7 @@ namespace BlackCore::Fsd void handleTextMessage(const QStringList &tokens); void handlePilotDataUpdate(const QStringList &tokens); void handleVisualPilotDataUpdate(const QStringList &tokens); + void handleVisualPilotDataToggle(const QStringList &tokens); void handleEuroscopeSimData(const QStringList &tokens); void handlePing(const QStringList &tokens); void handlePong(const QStringList &tokens); @@ -568,6 +569,7 @@ namespace BlackCore::Fsd static int constexpr c_updateVisualPositionIntervalMsec = 200; //!< interval for the VATSIM visual position updates (send our position and 6DOF velocity) static int constexpr c_sendFsdMsgIntervalMsec = 10; //!< interval for FSD send messages bool m_stoppedSendingVisualPositions = false; //!< for when velocity drops to zero + bool m_serverWantsVisualPositions = false; //!< there are interested clients in range }; } // ns diff --git a/src/blackcore/fsd/messagebase.h b/src/blackcore/fsd/messagebase.h index 63d4e65c9..db5892aab 100644 --- a/src/blackcore/fsd/messagebase.h +++ b/src/blackcore/fsd/messagebase.h @@ -40,6 +40,7 @@ enum class MessageType KillRequest, PilotDataUpdate, VisualPilotDataUpdate, + VisualPilotDataToggle, Ping, Pong, ServerError, diff --git a/src/blackcore/fsd/visualpilotdatatoggle.cpp b/src/blackcore/fsd/visualpilotdatatoggle.cpp new file mode 100644 index 000000000..254ef60a7 --- /dev/null +++ b/src/blackcore/fsd/visualpilotdatatoggle.cpp @@ -0,0 +1,48 @@ +/* Copyright (C) 2022 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +#include "visualpilotdatatoggle.h" +#include "pbh.h" +#include "serializer.h" + +#include "blackmisc/logmessage.h" + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; + +namespace BlackCore::Fsd +{ + VisualPilotDataToggle::VisualPilotDataToggle() : MessageBase() + { } + + VisualPilotDataToggle::VisualPilotDataToggle(const QString &sender, const QString &client, bool active) + : MessageBase(sender, {}), + m_client(client), + m_active(active) + { } + + QStringList VisualPilotDataToggle::toTokens() const + { + QStringList tokens; + tokens.push_back(m_sender); + tokens.push_back(m_client); + tokens.push_back(QString::number(m_active ? 1 : 0)); + return tokens; + } + + VisualPilotDataToggle VisualPilotDataToggle::fromTokens(const QStringList &tokens) + { + if (tokens.size() < 3) + { + CLogMessage(static_cast(nullptr)).debug(u"Wrong number of arguments."); + return {}; + } + + return VisualPilotDataToggle(tokens[0], tokens[1], tokens[2] == QStringLiteral("1")); + } +} diff --git a/src/blackcore/fsd/visualpilotdatatoggle.h b/src/blackcore/fsd/visualpilotdatatoggle.h new file mode 100644 index 000000000..bac626cc2 --- /dev/null +++ b/src/blackcore/fsd/visualpilotdatatoggle.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2022 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKCORE_FSD_VISUALPILOTDATATOGGLE_H +#define BLACKCORE_FSD_VISUALPILOTDATATOGGLE_H + +#include "messagebase.h" +#include "enums.h" + +namespace BlackCore::Fsd +{ + //! Message from server to start or stop sending visual pilot data updates. + class BLACKCORE_EXPORT VisualPilotDataToggle : public MessageBase + { + public: + //! Constructor + VisualPilotDataToggle(const QString &sender, const QString &client, bool active); + + //! Message converted to tokens + QStringList toTokens() const; + + //! Construct from tokens + static VisualPilotDataToggle fromTokens(const QStringList &tokens); + + //! PDU identifier + static QString pdu() { return "$SF"; } + + //! Properties + //! @{ + QString m_client; + bool m_active = false; + //! @} + + private: + VisualPilotDataToggle(); + }; + + //! Equal to operator + inline bool operator==(const VisualPilotDataToggle &lhs, const VisualPilotDataToggle &rhs) + { + return lhs.m_client == rhs.m_client && lhs.m_active == rhs.m_active; + } + + //! Not equal to operator + inline bool operator!=(const VisualPilotDataToggle &lhs, const VisualPilotDataToggle &rhs) + { + return !(lhs == rhs); + } +} + +#endif // guard diff --git a/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp b/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp index 617aa462f..1c68f38cc 100644 --- a/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp +++ b/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp @@ -444,7 +444,7 @@ namespace BlackFsdTest m_client->sendPilotDataUpdate(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.count(), 2); const QList arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 1); const CRawFsdMessage fsdMessage = arguments.at(0).value(); @@ -476,7 +476,7 @@ namespace BlackFsdTest m_client->sendPilotDataUpdate(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.count(), 2); QList arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 1); CRawFsdMessage fsdMessage = arguments.at(0).value(); @@ -509,7 +509,7 @@ namespace BlackFsdTest m_client->sendPilotDataUpdate(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.count(), 2); QList arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 1); CRawFsdMessage fsdMessage = arguments.at(0).value(); diff --git a/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp b/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp index ee713a8e9..fc22232fc 100644 --- a/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp +++ b/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp @@ -38,6 +38,7 @@ #include "blackcore/fsd/servererror.h" #include "blackcore/fsd/interimpilotdataupdate.h" #include "blackcore/fsd/visualpilotdataupdate.h" +#include "blackcore/fsd/visualpilotdatatoggle.h" #include "blackcore/fsd/planeinforequest.h" #include "blackcore/fsd/planeinformation.h" #include "blackcore/fsd/planeinforequestfsinn.h" @@ -86,6 +87,7 @@ namespace BlackMiscTest void testPBH(); void testPilotDataUpdate(); void testVisualPilotDataUpdate(); + void testVisualPilotDataToggle(); void testPing(); void testPlaneInfoRequest(); void testPlaneInformation(); @@ -543,6 +545,25 @@ namespace BlackMiscTest QCOMPARE(0.0, messageFromTokens.m_noseGearAngle); } + void CTestFsdMessages::testVisualPilotDataToggle() + { + const VisualPilotDataToggle message("SERVER", "ABCD", true); + + QCOMPARE(QString("SERVER"), message.sender()); + QCOMPARE(QString("ABCD"), message.m_client); + QCOMPARE(true, message.m_active); + + QString stringRef("SERVER:ABCD:1"); + QString str = message.toTokens().join(":"); + QCOMPARE(str, stringRef); + + QStringList tokens = QString("SERVER:ABCD:1").split(':'); + auto messageFromTokens = VisualPilotDataToggle::fromTokens(tokens); + QCOMPARE(QString("SERVER"), messageFromTokens.sender()); + QCOMPARE(QString("ABCD"), messageFromTokens.m_client); + QCOMPARE(true, messageFromTokens.m_active); + } + void CTestFsdMessages::testPing() { const Ping message("ABCD", "SERVER", "85275222");