mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
Ref T348, probe improvements
* use oldest probe (round robin) * only init probes once * release AI control for probes
This commit is contained in:
@@ -467,6 +467,22 @@ namespace BlackSimPlugin
|
||||
return CSimConnectObject();
|
||||
}
|
||||
|
||||
CSimConnectObject CSimConnectObjects::getOldestNotPendingProbe() const
|
||||
{
|
||||
CSimConnectObject oldestProbe;
|
||||
for (const CSimConnectObject &simObject : this->values())
|
||||
{
|
||||
if (simObject.getType() == CSimConnectObject::TerrainProbe && !simObject.isPending())
|
||||
{
|
||||
if (!oldestProbe.hasCreatedTimestamp() || oldestProbe.getCreatedTimestamp() > simObject.getCreatedTimestamp())
|
||||
{
|
||||
oldestProbe = simObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldestProbe;
|
||||
}
|
||||
|
||||
bool CSimConnectObjects::containsType(CSimConnectObject::SimObjectType type) const
|
||||
{
|
||||
for (const CSimConnectObject &simObject : this->values())
|
||||
|
||||
@@ -373,6 +373,9 @@ namespace BlackSimPlugin
|
||||
//! Get a non pending probe
|
||||
CSimConnectObject getNotPendingProbe() const;
|
||||
|
||||
//! Get a non pending probe
|
||||
CSimConnectObject getOldestNotPendingProbe() const;
|
||||
|
||||
//! Contains object of type
|
||||
bool containsType(CSimConnectObject::SimObjectType type) const;
|
||||
};
|
||||
|
||||
@@ -288,8 +288,9 @@ namespace BlackSimPlugin
|
||||
if (this->isShuttingDownOrDisconnected()) { return false; }
|
||||
if (!this->isUsingFsxTerrainProbe()) { return false; }
|
||||
if (reference.isNull()) { return false; }
|
||||
const CSimConnectObject simObject = m_simConnectObjects.getNotPendingProbe();
|
||||
const CSimConnectObject simObject = m_simConnectObjects.getOldestNotPendingProbe(); // probes round robin
|
||||
if (!simObject.isConfirmedAdded()) { return false; }
|
||||
m_simConnectObjects[simObject.getCallsign()].resetTimestampToNow(); // mark as just used
|
||||
|
||||
CCoordinateGeodetic pos(reference);
|
||||
pos.setGeodeticHeight(terrainProbeAltitude());
|
||||
@@ -494,6 +495,15 @@ namespace BlackSimPlugin
|
||||
return id;
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFsxCommon::releaseAIControl(SIMCONNECT_OBJECT_ID objectId, SIMCONNECT_DATA_REQUEST_ID requestId)
|
||||
{
|
||||
HRESULT hr = SimConnect_AIReleaseControl(m_hSimConnect, objectId, requestId);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeLat, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAlt, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAtt, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::isValidSimObjectNotPendingRemoved(const CSimConnectObject &simObject) const
|
||||
{
|
||||
if (!simObject.hasValidRequestAndObjectId()) { return false; }
|
||||
@@ -640,7 +650,8 @@ namespace BlackSimPlugin
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_useFsxTerrainProbe && m_addedProbes < 1)
|
||||
// init terrain probes here has the advantage we can also switch it on/off at runtime
|
||||
if (m_useFsxTerrainProbe && !m_initFsxTerrainProbes)
|
||||
{
|
||||
this->physicallyInitAITerrainProbes(position, 2);
|
||||
}
|
||||
@@ -816,10 +827,7 @@ namespace BlackSimPlugin
|
||||
// P3D also has SimConnect_AIReleaseControlEx which also allows to destroy the aircraft
|
||||
const DWORD objectId = simObject.getObjectId();
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectMisc);
|
||||
HRESULT hr = SimConnect_AIReleaseControl(m_hSimConnect, objectId, requestId);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeLat, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAlt, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
hr += SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAtt, 1, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
const HRESULT hr = this->releaseAIControl(objectId, requestId);
|
||||
|
||||
if (isFailure(hr))
|
||||
{
|
||||
@@ -867,12 +875,16 @@ namespace BlackSimPlugin
|
||||
if (!simObject.isAircraft()) { return; }
|
||||
|
||||
CLogMessage(this).warning("Model failed to be added: '%1' details: %2") << simObject.getAircraftModelString() << simObject.getAircraft().toQString(true);
|
||||
CLogMessage::preformatted(this->verifyFailedAircraftInfo(simObject));
|
||||
CStatusMessage verifyMsg;
|
||||
const bool canBeUsed = this->verifyFailedAircraftInfo(simObject, verifyMsg);
|
||||
m_simConnectObjects.removeByOtherSimObject(simObject);
|
||||
if (verifyMsg.isEmpty()) { CLogMessage::preformatted(verifyMsg); }
|
||||
|
||||
if (simObject.getAddingExceptions() >= ThresholdAddException)
|
||||
if (!canBeUsed || simObject.getAddingExceptions() >= ThresholdAddException)
|
||||
{
|
||||
const CStatusMessage m = CLogMessage(this).warning("Model %1 failed %2 time(s) before and will be disabled") << simObject.toQString() << simObject.getAddingExceptions();
|
||||
const CStatusMessage m = !canBeUsed ?
|
||||
CLogMessage(this).warning("Model '%1' %2 failed verification and will be disabled") << simObject.getAircraftModelString() << simObject.toQString() :
|
||||
CLogMessage(this).warning("Model '%1' %2 failed %3 time(s) before and will be disabled") << simObject.getAircraftModelString() << simObject.toQString() << simObject.getAddingExceptions();
|
||||
this->updateAircraftEnabled(simObject.getCallsign(), false); // disable
|
||||
emit this->physicallyAddingRemoteModelFailed(simObject.getAircraft(), true, m);
|
||||
}
|
||||
@@ -892,13 +904,14 @@ namespace BlackSimPlugin
|
||||
}
|
||||
}
|
||||
|
||||
CStatusMessage CSimulatorFsxCommon::verifyFailedAircraftInfo(const CSimConnectObject &simObject)
|
||||
bool CSimulatorFsxCommon::verifyFailedAircraftInfo(const CSimConnectObject &simObject, CStatusMessage &details) const
|
||||
{
|
||||
CAircraftModel model = simObject.getAircraftModel();
|
||||
|
||||
const CSpecializedSimulatorSettings settings = this->getSimulatorSettings();
|
||||
const QStringList modelDirectories = settings.getModelDirectoriesFromSimulatorDirectoryOrDefault();
|
||||
const bool exists = CFsCommonUtil::adjustFileDirectory(model, settings.getModelDirectoriesOrDefault());
|
||||
bool canBeUsed = true;
|
||||
|
||||
CStatusMessageList messages;
|
||||
if (exists)
|
||||
@@ -908,7 +921,8 @@ namespace BlackSimPlugin
|
||||
const CAircraftCfgEntriesList entries = CAircraftCfgParser::performParsingOfSingleFile(model.getFileName(), parsed, messages);
|
||||
if (parsed && !entries.containsTitle(model.getModelString()))
|
||||
{
|
||||
messages.push_back(CStatusMessage(this).warning("Model '%1' no longer in file '%2'. Models are: %3") << model.getModelString());
|
||||
messages.push_back(CStatusMessage(this).warning("Model '%1' no longer in re-parsed file '%2'. Models are: %3") << model.getModelString() << model.getFileName() << entries.getTitlesAsString(true));
|
||||
canBeUsed = false; // absolute no chance to use that one
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -921,14 +935,43 @@ namespace BlackSimPlugin
|
||||
}
|
||||
|
||||
// as single message
|
||||
return messages.toSingleMessage();
|
||||
details = messages.toSingleMessage();
|
||||
|
||||
// status
|
||||
return canBeUsed;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::logVerifyFailedAircraftInfo(const CSimConnectObject &simObject) const
|
||||
{
|
||||
CStatusMessage m;
|
||||
const bool r = verifyFailedAircraftInfo(simObject, m);
|
||||
if (!m.isEmpty()) { CLogMessage::preformatted(m); }
|
||||
return r;
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::verifyAddedTerrainProbe(const CSimulatedAircraft &remoteAircraftIn)
|
||||
{
|
||||
CSimConnectObject &simObject = m_simConnectObjects[remoteAircraftIn.getCallsign()];
|
||||
simObject.setConfirmedAdded(true);
|
||||
CLogMessage(this).info("Probe: '%1' confirmed, %2") << simObject.getCallsignAsString() << simObject.toQString();
|
||||
HRESULT hr;
|
||||
CCallsign cs;
|
||||
|
||||
// no simObject reference outside that block, because it will be deleted
|
||||
{
|
||||
CSimConnectObject &simObject = m_simConnectObjects[remoteAircraftIn.getCallsign()];
|
||||
simObject.setConfirmedAdded(true);
|
||||
simObject.resetTimestampToNow();
|
||||
CLogMessage(this).info("Probe: '%1' '%2' confirmed, %3") << simObject.getCallsignAsString() << simObject.getAircraftModelString() << simObject.toQString();
|
||||
|
||||
SIMCONNECT_OBJECT_ID objectId = simObject.getObjectId();
|
||||
SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId();
|
||||
hr = this->releaseAIControl(objectId, requestId);
|
||||
cs = simObject.getCallsign();
|
||||
}
|
||||
|
||||
if (isFailure(hr))
|
||||
{
|
||||
CLogMessage(this).info("Disable probes: '%1' failed to relase control") << cs.asString();
|
||||
m_useFsxTerrainProbe = false;
|
||||
}
|
||||
|
||||
// trigger new adding from pending if any
|
||||
if (!m_addPendingAircraft.isEmpty())
|
||||
@@ -1053,7 +1096,7 @@ namespace BlackSimPlugin
|
||||
}
|
||||
|
||||
// in all cases add verification details
|
||||
CLogMessage::preformatted(this->verifyFailedAircraftInfo(simObject));
|
||||
this->logVerifyFailedAircraftInfo(simObject);
|
||||
|
||||
// relay messages
|
||||
if (!msg.isEmpty()) { emit this->driverMessages(msg); }
|
||||
@@ -1333,8 +1376,6 @@ namespace BlackSimPlugin
|
||||
const bool sendGround = setup.isSendingGndFlagToSimulator();
|
||||
|
||||
// FSX/P3D adding
|
||||
Q_ASSERT_X(!probe || m_useFsxTerrainProbe, Q_FUNC_INFO, "Adding probe, but FSX probe mode is off");
|
||||
|
||||
bool adding = false; // will be added flag
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = probe ? this->obtainRequestIdForSimObjTerrainProbe() : this->obtainRequestIdForSimObjAircraft();
|
||||
const SIMCONNECT_DATA_INITPOSITION initialPosition = CSimulatorFsxCommon::aircraftSituationToFsxPosition(newRemoteAircraft.getSituation(), sendGround);
|
||||
@@ -1344,6 +1385,8 @@ namespace BlackSimPlugin
|
||||
const HRESULT hr = !probe ?
|
||||
SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, requestId) :
|
||||
SimConnect_AICreateSimulatedObject(m_hSimConnect, qPrintable(modelString), initialPosition, requestId);
|
||||
// const HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, requestId);
|
||||
|
||||
if (isFailure(hr))
|
||||
{
|
||||
const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create AI traffic: '%1' '%2'") << callsign.toQString() << modelString;
|
||||
@@ -1369,10 +1412,11 @@ namespace BlackSimPlugin
|
||||
Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread");
|
||||
|
||||
// static const QString modelString("OrcaWhale");
|
||||
// static const QString modelString("Water Drop");
|
||||
// static const QString modelString("Water Drop"); // not working on P3Dx86/FSX, no requests on that id possible
|
||||
// static const QString modelString("A321ACA");
|
||||
// static const QString modelString("AI_Tracker_Object_0");
|
||||
static const QString modelString("Water Drop");
|
||||
// static const QString modelString("Piper Cub"); // P3Dv86 works as nonATC/SimulatedObject
|
||||
static const QString modelString("Discovery Spaceshuttle"); // P3Dx86 works as nonATC/SimulatedObject
|
||||
static const QString pseudoCallsign("PROBE%1"); // max 12 chars
|
||||
static const CCountry ctry("SW", "SWIFT");
|
||||
static const CAirlineIcaoCode swiftAirline("SWI", "swift probe", ctry, "SWIFT", false, false);
|
||||
@@ -1390,6 +1434,8 @@ namespace BlackSimPlugin
|
||||
int CSimulatorFsxCommon::physicallyInitAITerrainProbes(const ICoordinateGeodetic &coordinate, int number)
|
||||
{
|
||||
if (number < 1) { return 0; }
|
||||
if (m_initFsxTerrainProbes) { return m_addedProbes; }
|
||||
m_initFsxTerrainProbes = true; // no multiple inits
|
||||
int c = 0;
|
||||
for (int n = 1; n <= number; ++n)
|
||||
{
|
||||
@@ -1728,7 +1774,7 @@ namespace BlackSimPlugin
|
||||
// in case we sent, we sent everything
|
||||
HRESULT hr1 = this->logAndTraceSendId(
|
||||
SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts,
|
||||
objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0,
|
||||
static_cast<SIMCONNECT_OBJECT_ID>(objectId), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0,
|
||||
sizeof(DataDefinitionRemoteAircraftPartsWithoutLights), &ddRemoteAircraftPartsWithoutLights),
|
||||
traceId, simObject, "Failed so set parts", Q_FUNC_INFO, "SimConnect_SetDataOnSimObject");
|
||||
|
||||
@@ -1955,9 +2001,9 @@ namespace BlackSimPlugin
|
||||
const DWORD objectId = simObject.getObjectId();
|
||||
const HRESULT result = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(
|
||||
m_hSimConnect, requestId,
|
||||
m_hSimConnect, static_cast<SIMCONNECT_DATA_REQUEST_ID>(requestId),
|
||||
CSimConnectDefinitions::DataRemoteAircraftGetPosition,
|
||||
objectId, SIMCONNECT_PERIOD_ONCE),
|
||||
static_cast<SIMCONNECT_OBJECT_ID>(objectId), SIMCONNECT_PERIOD_ONCE),
|
||||
simObject, w.arg(requestId), Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
const bool ok = isOk(result);
|
||||
if (ok) { m_pendingProbeRequests.insert(requestId, aircraftCallsign); }
|
||||
@@ -2049,6 +2095,7 @@ namespace BlackSimPlugin
|
||||
m_dispatchErrors = 0;
|
||||
m_receiveExceptionCount = 0;
|
||||
m_addedProbes = 0;
|
||||
m_initFsxTerrainProbes = false;
|
||||
m_sendIdTraces.clear();
|
||||
}
|
||||
|
||||
@@ -2199,7 +2246,7 @@ namespace BlackSimPlugin
|
||||
|
||||
const CAltitude &CSimulatorFsxCommon::terrainProbeAltitude()
|
||||
{
|
||||
static const CAltitude alt(10000, CLengthUnit::ft());
|
||||
static const CAltitude alt(50000, CLengthUnit::ft());
|
||||
return alt;
|
||||
}
|
||||
|
||||
|
||||
@@ -238,6 +238,9 @@ namespace BlackSimPlugin
|
||||
//! Get new request id, overflow safe
|
||||
SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForSimObjTerrainProbe();
|
||||
|
||||
//! Release AI control
|
||||
HRESULT releaseAIControl(SIMCONNECT_OBJECT_ID objectId, SIMCONNECT_DATA_REQUEST_ID requestId);
|
||||
|
||||
//! Valid CSimConnectObject which is NOT pendig removed
|
||||
bool isValidSimObjectNotPendingRemoved(const CSimConnectObject &simObject) const;
|
||||
|
||||
@@ -256,7 +259,8 @@ namespace BlackSimPlugin
|
||||
CSimConnectObjects m_simConnectObjects; //!< AI objects and their object and request ids
|
||||
|
||||
// probes
|
||||
bool m_useFsxTerrainProbe = true; //!< Use FSX Terrain probe?
|
||||
bool m_useFsxTerrainProbe = true; //!< Use FSX Terrain probe?
|
||||
bool m_initFsxTerrainProbes = false; //!< initialized terrain probes
|
||||
int m_addedProbes = 0; //!< added probes
|
||||
QMap<DWORD, BlackMisc::Aviation::CCallsign> m_pendingProbeRequests; //!< pending elevation requests: requestId/aircraft callsign
|
||||
|
||||
@@ -302,7 +306,10 @@ namespace BlackSimPlugin
|
||||
void addingAircraftFailed(const CSimConnectObject &simObject);
|
||||
|
||||
//! Create a detailed info about the failed aircraft
|
||||
BlackMisc::CStatusMessage verifyFailedAircraftInfo(const CSimConnectObject &simObject);
|
||||
bool verifyFailedAircraftInfo(const CSimConnectObject &simObject, BlackMisc::CStatusMessage &details) const;
|
||||
|
||||
//! Logging version of verifyFailedAircraftInfo
|
||||
bool logVerifyFailedAircraftInfo(const CSimConnectObject &simObject) const;
|
||||
|
||||
//! Verify the probe
|
||||
void verifyAddedTerrainProbe(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraftIn);
|
||||
|
||||
Reference in New Issue
Block a user