diff --git a/src/plugins/simulator/fs9/fs9_client.cpp b/src/plugins/simulator/fs9/fs9_client.cpp index 0eb3de8c3..f889cadfb 100644 --- a/src/plugins/simulator/fs9/fs9_client.cpp +++ b/src/plugins/simulator/fs9/fs9_client.cpp @@ -28,10 +28,10 @@ namespace BlackSimPlugin { namespace Fs9 { - CFs9Client::CFs9Client( - BlackCore::IInterpolator *interpolator, QObject *owner, const BlackMisc::Aviation::CCallsign &callsign, const CTime &updateInterval) : + CFs9Client::CFs9Client(const CCallsign &callsign, const QString &modelName, + BlackCore::IInterpolator *interpolator, const CTime &updateInterval, QObject *owner) : CDirectPlayPeer(owner, callsign), - m_updateInterval(updateInterval), m_interpolator(interpolator) + m_updateInterval(updateInterval), m_interpolator(interpolator), m_modelName(modelName) { } @@ -183,8 +183,9 @@ namespace BlackSimPlugin callsign.toQString().toWCharArray(wszPlayername.data()); wszPlayername[callsign.toQString().size()] = 0; + Q_ASSERT(!m_modelName.isEmpty()); ZeroMemory(&m_playerInfo, sizeof(PLAYER_INFO_STRUCT)); - strcpy(m_playerInfo.szAircraft, "Boeing 737-400 Paint1"); + strcpy(m_playerInfo.szAircraft, qPrintable(m_modelName)); m_playerInfo.dwFlags = 6; // Prepare and set the player information structure. @@ -222,7 +223,7 @@ namespace BlackSimPlugin MPChangePlayerPlane mpChangePlayerPlane; mpChangePlayerPlane.engine = CFs9Sdk::ENGINE_TYPE_JET; - mpChangePlayerPlane.aircraft_name = "Boeing 737-400"; + mpChangePlayerPlane.aircraft_name = m_modelName; QByteArray message; MultiPlayerPacketParser::writeType(message, CFs9Sdk::MULTIPLAYER_PACKET_ID_CHANGE_PLAYER_PLANE); MultiPlayerPacketParser::writeSize(message, mpChangePlayerPlane.size()); diff --git a/src/plugins/simulator/fs9/fs9_client.h b/src/plugins/simulator/fs9/fs9_client.h index 4fafbff42..688d66053 100644 --- a/src/plugins/simulator/fs9/fs9_client.h +++ b/src/plugins/simulator/fs9/fs9_client.h @@ -39,7 +39,9 @@ namespace BlackSimPlugin }; //! Constructor - CFs9Client(BlackCore::IInterpolator *interpolator, QObject *owner, const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CTime &updateInterval); + CFs9Client(const BlackMisc::Aviation::CCallsign &callsign, const QString &modelName, + BlackCore::IInterpolator *interpolator, const BlackMisc::PhysicalQuantities::CTime &updateInterval, + QObject *owner); //! Destructor virtual ~CFs9Client(); @@ -89,6 +91,7 @@ namespace BlackSimPlugin BlackMisc::PhysicalQuantities::CTime m_updateInterval; BlackCore::IInterpolator *m_interpolator = nullptr; + QString m_modelName; int m_timerId = 0; IDirectPlay8Address *m_hostAddress = nullptr; diff --git a/src/plugins/simulator/fs9/simulator_fs9.cpp b/src/plugins/simulator/fs9/simulator_fs9.cpp index 27b5fb41d..14963b2d4 100644 --- a/src/plugins/simulator/fs9/simulator_fs9.cpp +++ b/src/plugins/simulator/fs9/simulator_fs9.cpp @@ -20,6 +20,7 @@ #include "blackmisc/project.h" #include "blackmisc/logmessage.h" #include "blackmisc/propertyindexallclasses.h" +#include "blackmisc/simulation/fscommon/fscommonutil.h" #include #include @@ -30,6 +31,7 @@ using namespace BlackMisc::Simulation; using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Geo; using namespace BlackMisc::Simulation; +using namespace BlackMisc::Simulation::FsCommon; using namespace BlackSimPlugin::Fs9; using namespace BlackSimPlugin::FsCommon; @@ -52,10 +54,17 @@ namespace BlackSimPlugin IRemoteAircraftProvider *remoteAircraftProvider, IPluginStorageProvider *pluginStorageProvider, QObject *parent) : - CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, pluginStorageProvider, parent) + CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, pluginStorageProvider, + aircraftObjectsDir(), excludeDirectories(), parent) { connect(lobbyClient.data(), &CLobbyClient::disconnected, this, std::bind(&CSimulatorFs9::simulatorStatusChanged, this, 0)); this->m_interpolator = new BlackCore::CInterpolatorLinear(remoteAircraftProvider, this); + m_modelMatcher.setDefaultModel(CAircraftModel( + "Boeing 737-400", + CAircraftModel::TypeModelMatchingDefaultModel, + "B737-400 default model", + CAircraftIcaoData(CAircraftIcaoCode("B734", "L2J"), CAirlineIcaoCode(), "FFFFFF") + )); } bool CSimulatorFs9::isConnected() const @@ -111,7 +120,17 @@ namespace BlackSimPlugin this->physicallyRemoveRemoteAircraft(callsign); } - CFs9Client *client = new CFs9Client(m_interpolator, this, callsign, CTime(25, CTimeUnit::ms())); + CSimulatedAircraft newRemoteAircraftCopy(newRemoteAircraft); + // matched models + CAircraftModel aircraftModel = getClosestMatch(newRemoteAircraftCopy); + Q_ASSERT(newRemoteAircraft.getCallsign() == aircraftModel.getCallsign()); + updateAircraftModel(newRemoteAircraft.getCallsign(), aircraftModel, simulatorOriginator()); + updateAircraftRendered(newRemoteAircraft.getCallsign(), true, simulatorOriginator()); + CSimulatedAircraft aircraftAfterModelApplied (getAircraftInRangeForCallsign(newRemoteAircraft.getCallsign())); + aircraftAfterModelApplied.setRendered(true); + emit modelMatchingCompleted(aircraftAfterModelApplied); + + CFs9Client *client = new CFs9Client(callsign, aircraftModel.getModelString(), m_interpolator, CTime(25, CTimeUnit::ms()), this); client->setHostAddress(fs9Host->getHostAddress()); client->setPlayerUserId(fs9Host->getPlayerUserId()); diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.cpp b/src/plugins/simulator/fscommon/simulator_fscommon.cpp index 0579906b4..5acbe0950 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.cpp +++ b/src/plugins/simulator/fscommon/simulator_fscommon.cpp @@ -10,7 +10,7 @@ #include "simulator_fscommon.h" #include "blackmisc/logmessage.h" #include "blackmisc/simulation/fscommon/modelmappingsprovidervpilot.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/blackmiscfreefunctions.h" using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Simulation; @@ -30,22 +30,37 @@ namespace BlackSimPlugin IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *renderedAircraftProvider, IPluginStorageProvider *pluginStorageProvider, + QString simRootDirectory, + QStringList excludedDirectories, QObject *parent) : CSimulatorCommon(info, ownAircraftProvider, renderedAircraftProvider, pluginStorageProvider, parent), - m_fsuipc(new CFsuipc()) + m_fsuipc(new CFsuipc()), + m_aircraftCfgParser(simRootDirectory, excludedDirectories), + m_modelMatcher(CAircraftMatcher::AllModes, this) { // hack to init mapper - CAircraftMapper *mapper = mapperInstance(); - connect(mapper, &CAircraftMapper::initCompleted, this, &CSimulatorFsCommon::ps_mapperInitialized); - mapper->initCompletelyInBackground(); + connect(&m_modelMatcher, &CAircraftMatcher::initializationFinished, this, &CSimulatorFsCommon::ps_mapperInitialized); + auto modelMappingsProvider = std::unique_ptr{ BlackMisc::make_unique(true) }; + m_modelMatcher.setModelMappingProvider(std::move(modelMappingsProvider)); + + CVariant aircraftCfg = getPluginData(this, "aircraft_cfg"); + if (aircraftCfg.isValid()) + { + m_modelMatcher.setInstalledModels(aircraftCfg.value().toAircraftModelList()); + } + else + { + connect(&m_aircraftCfgParser, &CAircraftCfgParser::parsingFinished, this, &CSimulatorFsCommon::ps_aircraftCfgParsingFinished); + m_aircraftCfgParser.parse(); + } } CSimulatorFsCommon::~CSimulatorFsCommon() { } - void CSimulatorFsCommon::ps_mapperInitialized(bool success) + void CSimulatorFsCommon::ps_mapperInitialized() { - if (success) { emit this->installedAircraftModelsChanged(); } + emit this->installedAircraftModelsChanged(); } bool CSimulatorFsCommon::disconnectFrom() @@ -101,139 +116,41 @@ namespace BlackSimPlugin void CSimulatorFsCommon::reverseLookupIcaoData(CAircraftModel &model) { - if (mapperInstance() && mapperInstance()->isInitialized()) + if (m_modelMatcher.isInitialized()) { // reverse lookup of ICAO - CAircraftIcaoData icao = mapperInstance()->getIcaoForModelString(model.getModelString()); + CAircraftIcaoData icao = m_modelMatcher.getIcaoForModelString(model.getModelString()); icao.updateMissingParts(model.getIcao()); model.setIcao(icao); // now best ICAO info in model } } - CAircraftMapper *CSimulatorFsCommon::mapperInstance() + CAircraftModel CSimulatorFsCommon::getClosestMatch(const CSimulatedAircraft &remoteAircraft) { - static CModelMappingsProviderVPilot *mappings = new CModelMappingsProviderVPilot(true); - - // tries to access simObjectsDir, if this is an mapped remote directory - // init might hang for a while - static CAircraftMapper *mapper = new CAircraftMapper( - std::unique_ptr(mappings), // currently hard wired - simObjectsDir() - ); - return mapper; - } - - CAircraftModel CSimulatorFsCommon::modelMatching(const CSimulatedAircraft &remoteAircraft) - { - //! \todo Model Matching before models are read - - // default model - CAircraftModel aircraftModel(remoteAircraft); // set defaults - - // Manually set string? - if (remoteAircraft.getModel().hasManuallySetString()) - { - // manual set model, maybe update missing parts - aircraftModel.updateMissingParts(remoteAircraft.getModel()); - CSimulatorFsCommon::reverseLookupIcaoData(aircraftModel); - return aircraftModel; - } - - // mapper ready? - if (!mapperInstance()->isInitialized()) - { - // will be removed later, just for experimental version - aircraftModel = CAircraftMapper::getDefaultModel(); - aircraftModel.setCallsign(remoteAircraft.getCallsign()); - CLogMessage(static_cast(nullptr)).warning("Mapper not ready, set to default model"); - return aircraftModel; - } - - // Model by queried string - const CClient remoteClient = remoteAircraft.getClient(); - if (remoteClient.getAircraftModel().hasQueriedModelString()) - { - QString directModelString = remoteClient.getAircraftModel().getModelString(); - if (!directModelString.isEmpty() && mapperInstance()->containsModelWithTitle(directModelString)) - { - aircraftModel = mapperInstance()->getModelWithTitle(directModelString); - aircraftModel.setModelType(CAircraftModel::TypeQueriedFromNetwork); - } - } - - // ICAO to model - if (!aircraftModel.hasModelString()) - { - CAircraftIcaoData icao = remoteAircraft.getIcaoInfo(); - BlackMisc::Network::CAircraftMappingList mappingList = mapperInstance()->getAircraftMappingList().findByIcaoAircraftAndAirlineDesignator(icao, true); - if (!mappingList.isEmpty()) - { - CAircraftModel modelFromMappings = mappingList.front().getModel(); - // now turn the model from the mapping rules into a model from the simulator which has more metadata - aircraftModel = mapperInstance()->getModelWithTitle(modelFromMappings.getModelString()); - Q_ASSERT(aircraftModel.getModelString() == modelFromMappings.getModelString()); - aircraftModel.updateMissingParts(modelFromMappings); // update ICAO - aircraftModel.setModelType(CAircraftModel::TypeModelMatching); - } - } - - // default or sanity check - if (!aircraftModel.hasModelString()) - { - aircraftModel = CAircraftMapper::getDefaultModel(); - } - else - { - // check, do we have the model on disk - if (!mapperInstance()->containsModelWithTitle(aircraftModel.getModelString())) - { - const QString m = QString("Missing model: %1").arg(aircraftModel.getModelString()); - Q_ASSERT_X(false, "modelMatching", m.toLocal8Bit().constData()); - } - } - aircraftModel.setCallsign(remoteAircraft.getCallsign()); - - Q_ASSERT(!aircraftModel.getCallsign().isEmpty()); - Q_ASSERT(aircraftModel.hasModelString()); - Q_ASSERT(aircraftModel.getModelType() != CAircraftModel::TypeUnknown); - return aircraftModel; - } - - QString CSimulatorFsCommon::simObjectsDir() - { - //! \todo add FS9 dir - QString dir = CFsCommonUtil::fsxSimObjectsDirFromRegistry(); - if (!dir.isEmpty()) { return dir; } - return "P:/FlightSimulatorX (MSI)/SimObjects"; - // "p:/temp/SimObjects" + return m_modelMatcher.getClosestMatch(remoteAircraft); } CAircraftModelList CSimulatorFsCommon::getInstalledModels() const { - if (!mapperInstance()) { return CAircraftModelList(); } - return mapperInstance()->getAircraftCfgEntriesList().toAircraftModelList(); + return m_aircraftCfgParser.getAircraftCfgEntriesList().toAircraftModelList(); } CAircraftIcaoData CSimulatorFsCommon::getIcaoForModelString(const QString &modelString) const { - if (!mapperInstance()) { return CAircraftIcaoData(); } - return mapperInstance()->getIcaoForModelString(modelString); + if (!m_modelMatcher.isInitialized()) { return CAircraftIcaoData(); } + return m_modelMatcher.getIcaoForModelString(modelString); } void CSimulatorFsCommon::reloadInstalledModels() { - if (mapperInstance()) - { - mapperInstance()->markUninitialized(); - mapperInstance()->initCompletelyInBackground(); - } + m_aircraftCfgParser.parse(); } CPixmap CSimulatorFsCommon::iconForModel(const QString &modelString) const { static const CPixmap empty; - if (modelString.isEmpty() || !mapperInstance()->isInitialized()) { return empty; } - CAircraftCfgEntriesList cfgEntries = mapperInstance()->getAircraftCfgEntriesList().findByTitle(modelString); + if (modelString.isEmpty()) { return empty; } + CAircraftCfgEntriesList cfgEntries = m_aircraftCfgParser.getAircraftCfgEntriesList().findByTitle(modelString); if (cfgEntries.isEmpty()) { CLogMessage(this).warning("No .cfg entry for '%1'") << modelString; @@ -292,5 +209,14 @@ namespace BlackSimPlugin CSimulatorCommon::enableDebugMessages(driver, interpolator); } + void CSimulatorFsCommon::ps_aircraftCfgParsingFinished() + { + setPluginData(this, "aircraft_cfg", m_aircraftCfgParser.getAircraftCfgEntriesList().toCVariant()); + m_modelMatcher.setInstalledModels(m_aircraftCfgParser.getAircraftCfgEntriesList().toAircraftModelList()); + + // Now the matcher has all required information to be initialized + m_modelMatcher.init(); + } + } // namespace } // namespace diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.h b/src/plugins/simulator/fscommon/simulator_fscommon.h index 664218854..eaeca737c 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.h +++ b/src/plugins/simulator/fscommon/simulator_fscommon.h @@ -14,7 +14,8 @@ #include "blackcore/simulator_common.h" #include "blackcore/interpolator.h" -#include "blackmisc/simulation/fscommon/aircraftmapper.h" +#include "blackmisc/simulation/fscommon/aircraftmatcher.h" +#include "blackmisc/simulation/fscommon/aircraftcfgparser.h" #include "fsuipc.h" #include @@ -37,10 +38,7 @@ namespace BlackSimPlugin bool isFsuipcConnected() const; //! Experimental model matching - static BlackMisc::Simulation::CAircraftModel modelMatching(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); - - //! SimObjects directory - static QString simObjectsDir(); + BlackMisc::Simulation::CAircraftModel getClosestMatch(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); //! \copydoc ISimulator::isPaused virtual bool isPaused() const override { return m_simPaused; } @@ -84,6 +82,8 @@ namespace BlackSimPlugin BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, BlackMisc::IPluginStorageProvider *pluginStorageProvider, + QString simRootDirectory, + QStringList excludedDirectories, QObject *parent = nullptr); QString simulatorDetails; //!< describes version etc. @@ -99,6 +99,8 @@ namespace BlackSimPlugin BlackMisc::Aviation::CComSystem m_simCom2; //!< cockpit COM2 state in simulator BlackMisc::Aviation::CTransponder m_simTransponder; //!< cockpit xpdr state in simulator + BlackMisc::Simulation::FsCommon::CAircraftCfgParser m_aircraftCfgParser; //!< aircraft.cfg parser + //! Set own model void setOwnAircraftModel(const BlackMisc::Simulation::CAircraftModel &model); @@ -106,15 +108,17 @@ namespace BlackSimPlugin void setOwnAircraftModel(const QString &modelName); //! Reverse lookup - static void reverseLookupIcaoData(BlackMisc::Simulation::CAircraftModel &model); + void reverseLookupIcaoData(BlackMisc::Simulation::CAircraftModel &model); - //! Get the mapper singleton - static BlackMisc::Simulation::FsCommon::CAircraftMapper *mapperInstance(); + BlackMisc::Simulation::FsCommon::CAircraftMatcher m_modelMatcher; //!< Model matcher protected slots: //! Mapper has been initialized - void ps_mapperInitialized(bool success); + void ps_mapperInitialized(); + + //! aircraft.cfg files parsing is finished + void ps_aircraftCfgParsingFinished(); }; } // namespace diff --git a/src/plugins/simulator/fsx/simulator_fsx.cpp b/src/plugins/simulator/fsx/simulator_fsx.cpp index cda3fb2e1..e102ad0e6 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx.cpp @@ -19,6 +19,7 @@ #include "blackmisc/aviation/airportlist.h" #include "blackmisc/logmessage.h" #include "blackmisc/network/aircraftmappinglist.h" +#include "blackmisc/simulation/fscommon/fscommonutil.h" #include #include @@ -43,7 +44,8 @@ namespace BlackSimPlugin IRemoteAircraftProvider *remoteAircraftProvider, IPluginStorageProvider *pluginStorageProvider, QObject *parent) : - CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, pluginStorageProvider, parent) + CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, pluginStorageProvider, + simObjectsDir(), excludeDirectories(), parent) { Q_ASSERT(ownAircraftProvider); Q_ASSERT(remoteAircraftProvider); @@ -51,6 +53,12 @@ namespace BlackSimPlugin m_useFsuipc = false; // do not use FSUIPC at the moment with FSX this->m_interpolator = new CInterpolatorLinear(remoteAircraftProvider, this); + m_modelMatcher.setDefaultModel(CAircraftModel( + "Boeing 737-800 Paint1", + CAircraftModel::TypeModelMatchingDefaultModel, + "B737-800 default model", + CAircraftIcaoData(CAircraftIcaoCode("B738", "L2J"), CAirlineIcaoCode(), "FFFFFF") + )); } CSimulatorFsx::~CSimulatorFsx() @@ -155,7 +163,7 @@ namespace BlackSimPlugin ++m_nextObjID; // matched models - CAircraftModel aircraftModel = modelMatching(newRemoteAircraft); + CAircraftModel aircraftModel = getClosestMatch(newRemoteAircraft); Q_ASSERT_X(newRemoteAircraft.getCallsign() == aircraftModel.getCallsign(), Q_FUNC_INFO, "mismatching callsigns"); this->updateAircraftModel(callsign, aircraftModel, simulatorOriginator()); @@ -899,5 +907,6 @@ namespace BlackSimPlugin { m_timer->stop(); } + } // namespace } // namespace