2504 lines
95 KiB
C++
Executable File
2504 lines
95 KiB
C++
Executable File
/**
|
|
* Connect to ngs / hla and provide the basic interface
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Christian Ehrlicher, SLSE, 2017-04-07
|
|
*/
|
|
|
|
|
|
#include "ngs_connector.h"
|
|
#include "ngs_handler.h"
|
|
#include "damage_model.h"
|
|
#include <Common/settings.h>
|
|
#include <Common/player_callback.h>
|
|
#include <Common/identifierstruct.h>
|
|
#include <Common/participantinformation.h>
|
|
|
|
#include "../Guez/rpr/rpr_observer_guez_human_cb_notifier.h"
|
|
#include "../Guez/rpr/rpr_observer_guez_groundvehicle_cb_notifier.h"
|
|
#include "../Guez/rpr/rpr_observer_guez_observer_controller_cb_notifier.h"
|
|
|
|
#include "../Guez/rpr/rpr_observer_guez_minefield_cb_notifier.h"
|
|
#include "../Guez/rpr/rpr_observer_guez_minefield_breach_cb_notifier.h"
|
|
#include "../Guez/rpr/rpr_observer_guez_fire_support_single_shot_cb_notifier.h"
|
|
|
|
#include "../Guez/rpr/rpr_ia_munitiondetonation.h"
|
|
#include "../Guez/rpr/rpr_ia_weaponfire.h"
|
|
#include "../Guez/rpr/rpr_ia_guez_hit.h"
|
|
#include "../Guez/rpr/rpr_ia_guez_init.h"
|
|
#include "../Guez/rpr/rpr_ia_guez_exconengagement.h"
|
|
#include "../Guez/rpr/rpr_ia_guez_bitereport.h"
|
|
#include "../Guez/rpr/rpr_ia_guez_requestbitereport.h"
|
|
|
|
#include <NGSException.h>
|
|
|
|
#include <QTimer>
|
|
#include <QPolygonF>
|
|
#include <QTransform>
|
|
#include <QDateTime>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
#include <AreaEffectSimulation/aes_enums.hpp>
|
|
|
|
#include <SimulatedWorldAPI.h>
|
|
#include <EventIdentifierStruct.h>
|
|
#include <SpatialStruct.h>
|
|
#include <IsPartOfStruct.h>
|
|
#include <EnvironmentObjectTypeStruct.h>
|
|
#include <BiteResultStruct.h>
|
|
|
|
#include <IObserverGuezHumanObjClass.h>
|
|
#include <IObserverGuezObserverControllerObjClass.h>
|
|
#include <IObserverGuezGroundVehicleObjClass.h>
|
|
|
|
#include <IObserverGuezMineFieldObjClass.h>
|
|
#include <IObserverGuezMineFieldBreachObjClass.h>
|
|
|
|
#include <IObserverMunitionDetonationIntClass.h>
|
|
#include <IObserverMunitionDetonationIntInstance.h>
|
|
#include <IObserverWeaponFireIntClass.h>
|
|
#include <IObserverWeaponFireIntInstance.h>
|
|
#include <IObserverGuezHitIntClass.h>
|
|
#include <IObserverGuezHitIntInstance.h>
|
|
#include <IObserverGuezInitIntClass.h>
|
|
#include <IObserverGuezInitIntInstance.h>
|
|
#include <IObserverGuezBiteReportIntClass.h>
|
|
#include <IObserverGuezRequestBiteReportIntClass.h>
|
|
|
|
#include <IPlayerGuezHumanObjClass.h>
|
|
#include <IPlayerGuezHumanObjInstance.h>
|
|
#include <IPlayerGuezObserverControllerObjClass.h>
|
|
#include <IPlayerGuezObserverControllerObjInstance.h>
|
|
#include <IPlayerGuezGroundVehicleObjClass.h>
|
|
#include <IPlayerGuezGroundVehicleObjInstance.h>
|
|
|
|
#include <IPlayerGuezMineFieldBreachObjClass.h>
|
|
#include <IPlayerGuezMineFieldBreachObjInstance.h>
|
|
#include <IPlayerGuezMineFieldObjClass.h>
|
|
#include <IPlayerGuezMineFieldObjInstance.h>
|
|
#include <IPlayerGuezChemicalAgentAreaObjClass.h>
|
|
#include <IPlayerGuezChemicalAgentAreaObjInstance.h>
|
|
#include <IPlayerGuezNuclearAgentAreaObjClass.h>
|
|
#include <IPlayerGuezNuclearAgentAreaObjInstance.h>
|
|
#include <IPlayerWeaponFireIntClass.h>
|
|
#include <IPlayerWeaponFireIntInstance.h>
|
|
|
|
#include <IPlayerGuezHitIntClass.h>
|
|
#include <IPlayerGuezHitIntInstance.h>
|
|
#include <IPlayerMunitionDetonationIntClass.h>
|
|
#include <IPlayerMunitionDetonationIntInstance.h>
|
|
|
|
#include <IPlayerGuezRequestBiteReportIntClass.h>
|
|
#include <IPlayerGuezRequestBiteReportIntInstance.h>
|
|
#include <IPlayerGuezBiteReportIntClass.h>
|
|
#include <IPlayerGuezBiteReportIntInstance.h>
|
|
#include <IPlayerGuezInitIntClass.h>
|
|
#include <IPlayerGuezInitIntInstance.h>
|
|
|
|
#include <IPlayerSOM.h>
|
|
|
|
using namespace AreaEffectSimulation;
|
|
|
|
namespace HighLevelArchitecture
|
|
{
|
|
|
|
static inline qint64 simTimeToMSec(const ngs::SimTime &st)
|
|
{
|
|
qint64 mSecs = st.getSeconds() * 1000LL;
|
|
mSecs += st.getMicroSeconds() / 1000;
|
|
return mSecs;
|
|
}
|
|
|
|
static inline rpr2::SpatialStruct spatialStructFromWorldLocation(const rpr2::WorldLocationStruct &wls)
|
|
{
|
|
rpr2::SpatialStaticStruct sss;
|
|
sss.WorldLocation = wls;
|
|
sss.IsFrozen = false;
|
|
sss.Orientation.Phi = 3.138309f;
|
|
sss.Orientation.Psi = 2.446645f;
|
|
sss.Orientation.Theta = -0.879588f;
|
|
rpr2::SpatialStruct ss;
|
|
|
|
ss.DeadReckoningAlgorithm__A__Alternatives.discriminant(rpr2::DeadReckoningAlgorithmEnum8::Static);
|
|
ss.DeadReckoningAlgorithm__A__Alternatives.SpatialStatic(sss);
|
|
|
|
return ss;
|
|
}
|
|
|
|
static inline rpr2::EnvironmentObjectTypeStruct dummyEOS()
|
|
{
|
|
return {2, 3, 4, 5};
|
|
}
|
|
|
|
//
|
|
// NgsConnector
|
|
//
|
|
|
|
NgsConnector::NgsConnector(const QString &fedName, NgsHandler *ngsHandler)
|
|
: m_ngsHandler(ngsHandler)
|
|
, m_fedName(fedName)
|
|
, m_swadmin(&ngs::SimulatedWorldAPI::getSimulatedWorldAdmin())
|
|
, m_master(nullptr)
|
|
, m_somPlayer(nullptr)
|
|
, m_playerCallback(new PlayerCallback())
|
|
, m_humanCallback(new ObserverGuezHumanCBNotifier())
|
|
, m_observerControllerCallback(new ObserverGuezObserverControllerCBNotifier())
|
|
, m_groundVehicleCallback(new ObserverGuezGroundVehicleCBNotifier())
|
|
, m_minefieldCallback(new ObserverGuezMineFieldCBNotifier())
|
|
, m_minefieldBreachCallback(new ObserverGuezMineFieldBreachCBNotifier())
|
|
, m_munitionDetonationCallback(new ObserverMunitionDetonationCBNotifier())
|
|
, m_weaponfireCallback(new ObserverWeaponFireCBNotifier())
|
|
, m_hitCallback(new ObserverGuezHitCBNotifier())
|
|
, m_initCallback(new ObserverGuezInitCBNotifier())
|
|
, m_biteReportCallback(new ObserverGuezBiteReportCBNotifier())
|
|
, m_requestBiteReportCallback(new ObserverGuezRequestBiteReportCBNotifier())
|
|
, m_bInitialized(false)
|
|
, m_bCanPublishData(false)
|
|
, m_timer(new QTimer(this))
|
|
, m_logger(getLogger("NgsConnector"))
|
|
{
|
|
connect(m_timer, &QTimer::timeout,
|
|
this, &NgsConnector::go);
|
|
connect(m_playerCallback, &PlayerCallback::firstTick,
|
|
this, &NgsConnector::onFirstTickFinished);
|
|
|
|
// Ground Vehicle
|
|
connectObserverGuezGroundVehicleObjectSignals(m_groundVehicleCallback);
|
|
|
|
// Human
|
|
connectObserverGuezHumanObjectSignals(m_humanCallback);
|
|
|
|
// Observer / Controller
|
|
connectObserverGuezObserverControllerObjectSignals(m_observerControllerCallback);
|
|
|
|
// Mine Field
|
|
connectObserverGuezMineFieldObjectSignals(m_minefieldCallback);
|
|
|
|
// Mine Field Breach
|
|
connectObserverGuezMineFieldBreachObjectSignals(m_minefieldBreachCallback);
|
|
|
|
// Munition Detonation
|
|
connect(m_munitionDetonationCallback, &ObserverMunitionDetonationCBNotifier::newMunitionDetonation,
|
|
this, &NgsConnector::onNewMunitionDetonation);
|
|
|
|
// Weapon Fire
|
|
connect(m_weaponfireCallback, &ObserverWeaponFireCBNotifier::newWeaponFire,
|
|
this, &NgsConnector::onNewWeaponFire);
|
|
|
|
// Hit
|
|
connect(m_hitCallback, &ObserverGuezHitCBNotifier::newGuezHit,
|
|
this, &NgsConnector::onNewGuezHit);
|
|
|
|
// Init
|
|
connect(m_initCallback, &ObserverGuezInitCBNotifier::newGuezInit,
|
|
this, &NgsConnector::onNewGuezInit);
|
|
|
|
// Request Bite Report
|
|
connect(m_requestBiteReportCallback, &ObserverGuezRequestBiteReportCBNotifier::newGuezRequestBiteReport,
|
|
this, &NgsConnector::onNewGuezRequestBiteReport);
|
|
|
|
// Bite Report
|
|
connect(m_biteReportCallback, &ObserverGuezBiteReportCBNotifier::newGuezBiteReport,
|
|
this, &NgsConnector::onNewGuezBiteReport);
|
|
}
|
|
|
|
NgsConnector::~NgsConnector()
|
|
{
|
|
uninitialize();
|
|
|
|
delete m_playerCallback;
|
|
|
|
delete m_humanCallback;
|
|
delete m_observerControllerCallback;
|
|
delete m_groundVehicleCallback;
|
|
delete m_minefieldCallback;
|
|
delete m_minefieldBreachCallback;
|
|
delete m_munitionDetonationCallback;
|
|
delete m_weaponfireCallback;
|
|
delete m_initCallback;
|
|
delete m_hitCallback;
|
|
delete m_requestBiteReportCallback;
|
|
delete m_biteReportCallback;
|
|
|
|
delete m_timer;
|
|
}
|
|
|
|
bool NgsConnector::initialize(ngs::IObserver::ProtocolType protocol, const QString &playerName, const QString &appDirPath)
|
|
{
|
|
QString swconf = appDirPath + QLatin1Char('/') + Settings::swConfFileName();
|
|
m_bInitialized = true;
|
|
|
|
// NGS Initialisation
|
|
try
|
|
{
|
|
m_master = &m_swadmin->getIFederationMaster(protocol, qPrintable(swconf), Settings::fomIdentifier().toStdString(), Settings::rtiIdentifier().toStdString()); // "", "MAK"
|
|
}
|
|
catch (const ngs::NGSSimWorldException &e)
|
|
{
|
|
ERROR_LOG(m_logger) << "caught exception during init (getIFederationMaster): " << e.print();
|
|
return false;
|
|
}
|
|
|
|
ngs::IPlayer *player = nullptr;
|
|
switch (protocol)
|
|
{
|
|
case ngs::IObserver::HLA:
|
|
{
|
|
try
|
|
{
|
|
m_master->createFederation(m_fedName.toStdString());
|
|
}
|
|
catch (const NGSException &e)
|
|
{
|
|
ERROR_LOG(m_logger) << "caught exception during init (createFederation): " << e.print();
|
|
return false;
|
|
}
|
|
player = &m_swadmin->getIPlayer(m_fedName.toStdString(), playerName.toStdString(), *m_playerCallback, Settings::swConfFileName().toLatin1().data(), Settings::fomIdentifier().toStdString(), Settings::rtiIdentifier().toStdString());
|
|
break;
|
|
}
|
|
case ngs::IObserver::CORBANOTIFY:
|
|
case ngs::IObserver::DIS:
|
|
{
|
|
unsigned char federationId = m_fedName.toUShort();
|
|
m_master->createFederation(federationId);
|
|
player = &m_swadmin->getIPlayer(federationId, playerName.toStdString(), *m_playerCallback, protocol, Settings::swConfFileName().toLatin1().data(), Settings::fomIdentifier().toStdString());
|
|
break;
|
|
}
|
|
}
|
|
m_somPlayer = dynamic_cast<rpr2::IPlayerSOM *>(player);
|
|
|
|
m_somPlayer->configureSimTime(ngs::IObserver::REALTIMECLOCK, ngs::SimTime(0, 0));
|
|
|
|
m_timer->start(10);
|
|
|
|
return true;
|
|
}
|
|
|
|
void NgsConnector::uninitialize()
|
|
{
|
|
if (!m_bInitialized)
|
|
return;
|
|
m_bInitialized = false;
|
|
|
|
m_timer->stop();
|
|
|
|
unsubscribeFromNgs();
|
|
if (m_swadmin)
|
|
m_swadmin->resignInterface();
|
|
if (m_somPlayer)
|
|
m_somPlayer->resignSimulatedWorld();
|
|
if (m_master)
|
|
{
|
|
m_master->destroyFederation(m_fedName.toStdString());
|
|
m_master->resignInterface();
|
|
m_master = nullptr;
|
|
}
|
|
}
|
|
|
|
void NgsConnector::subscribeAtNgs()
|
|
{
|
|
m_enitityNumberCounter = 1; // restart
|
|
m_eventCount = 1;
|
|
|
|
INFO_LOG(m_logger) << "Subscribe at NGS - Guez Human Objects";
|
|
rpr2::IObserverGuezHumanObjClass &humanObjClass = m_somPlayer->getObserverGuezHumanObjClass(*m_humanCallback);
|
|
humanObjClass.subscribeAllAttributes();
|
|
humanObjClass.subscribe();
|
|
|
|
INFO_LOG(m_logger) << "Subscribe at NGS - Guez ObserverController Objects";
|
|
rpr2::IObserverGuezObserverControllerObjClass &observerControllerObjClass = m_somPlayer->getObserverGuezObserverControllerObjClass(*m_observerControllerCallback);
|
|
observerControllerObjClass.subscribeAllAttributes();
|
|
observerControllerObjClass.subscribe();
|
|
|
|
INFO_LOG(m_logger) << "Subscribe at NGS - Guez GroundVehicle Objects";
|
|
rpr2::IObserverGuezGroundVehicleObjClass &groundVehicleObjClass = m_somPlayer->getObserverGuezGroundVehicleObjClass(*m_groundVehicleCallback);
|
|
groundVehicleObjClass.subscribeAllAttributes();
|
|
groundVehicleObjClass.subscribe();
|
|
|
|
INFO_LOG(m_logger) << "Subscribe at NGS - Guez MineField Objects";
|
|
rpr2::IObserverGuezMineFieldObjClass &minefieldObjClass = m_somPlayer->getObserverGuezMineFieldObjClass(*m_minefieldCallback);
|
|
minefieldObjClass.subscribeAllAttributes();
|
|
minefieldObjClass.subscribe();
|
|
|
|
INFO_LOG(m_logger) << "Subscribe at NGS - Guez MineField Breach Objects";
|
|
rpr2::IObserverGuezMineFieldBreachObjClass &minefieldBreachObjClass = m_somPlayer->getObserverGuezMineFieldBreachObjClass(*m_minefieldBreachCallback);
|
|
minefieldBreachObjClass.subscribeAllAttributes();
|
|
minefieldBreachObjClass.subscribe();
|
|
|
|
|
|
rpr2::IObserverMunitionDetonationIntClass &md = m_somPlayer->getObserverMunitionDetonationIntClass(*m_munitionDetonationCallback);
|
|
md.subscribe();
|
|
|
|
rpr2::IObserverWeaponFireIntClass &wfic = m_somPlayer->getObserverWeaponFireIntClass(*m_weaponfireCallback);
|
|
wfic.subscribe();
|
|
|
|
rpr2::IObserverGuezInitIntClass &giic = m_somPlayer->getObserverGuezInitIntClass(*m_initCallback);
|
|
giic.subscribe();
|
|
|
|
rpr2::IObserverGuezHitIntClass &ghic = m_somPlayer->getObserverGuezHitIntClass(*m_hitCallback);
|
|
ghic.subscribe();
|
|
|
|
rpr2::IObserverGuezRequestBiteReportIntClass &grbric = m_somPlayer->getObserverGuezRequestBiteReportIntClass(*m_requestBiteReportCallback);
|
|
grbric.subscribe();
|
|
|
|
rpr2::IObserverGuezBiteReportIntClass &gbric = m_somPlayer->getObserverGuezBiteReportIntClass(*m_biteReportCallback);
|
|
gbric.subscribe();
|
|
|
|
m_timer->start();
|
|
|
|
m_bCanPublishData = true;
|
|
}
|
|
|
|
|
|
void NgsConnector::unsubscribeFromNgs()
|
|
{
|
|
m_bCanPublishData = false;
|
|
|
|
if (m_somPlayer)
|
|
{
|
|
INFO_LOG(m_logger) << "Unsubscribe at NGS - Guez Human Objects";
|
|
rpr2::IObserverGuezHumanObjClass &humanObjClass = m_somPlayer->getObserverGuezHumanObjClass(*m_humanCallback);
|
|
humanObjClass.unsubscribe();
|
|
|
|
INFO_LOG(m_logger) << "Unsubscribe at NGS - Guez ObserverController Objects";
|
|
rpr2::IObserverGuezObserverControllerObjClass &observerControllerObjClass = m_somPlayer->getObserverGuezObserverControllerObjClass(*m_observerControllerCallback);
|
|
observerControllerObjClass.unsubscribe();
|
|
|
|
INFO_LOG(m_logger) << "Unsubscribe at NGS - Guez GroundVehicle Objects";
|
|
rpr2::IObserverGuezGroundVehicleObjClass &groundVehicleObjClass = m_somPlayer->getObserverGuezGroundVehicleObjClass(*m_groundVehicleCallback);
|
|
groundVehicleObjClass.unsubscribe();
|
|
|
|
INFO_LOG(m_logger) << "Unsubscribe at NGS - Guez MineField Objects";
|
|
rpr2::IObserverGuezMineFieldObjClass &minefieldObjClass = m_somPlayer->getObserverGuezMineFieldObjClass(*m_minefieldCallback);
|
|
minefieldObjClass.unsubscribe();
|
|
|
|
INFO_LOG(m_logger) << "Unsubscribe at NGS - Guez MineField Breach Objects";
|
|
rpr2::IObserverGuezMineFieldBreachObjClass &minefieldBreachObjClass = m_somPlayer->getObserverGuezMineFieldBreachObjClass(*m_minefieldBreachCallback);
|
|
minefieldBreachObjClass.unsubscribe();
|
|
}
|
|
|
|
for (rpr2::IPlayerBaseEntityObjInstance *player : qAsConst(m_playerMap))
|
|
player->deleteObjectInstance(getSimTime());
|
|
|
|
m_playerMap.clear();
|
|
|
|
for (rpr2::IPlayerEnvironmentObjectObjInstance *environmentObject : qAsConst(m_environmentObjects))
|
|
environmentObject->deleteObjectInstance(getSimTime());
|
|
|
|
m_environmentObjects.clear();
|
|
|
|
for (auto it = m_observerPlayerInstances.cbegin(); it != m_observerPlayerInstances.cend(); ++it)
|
|
emit virtualParticipantDeleted(it.key());
|
|
|
|
for (auto it = m_observerEnvironmentObjects.cbegin(); it != m_observerEnvironmentObjects.cend(); ++it)
|
|
emit virtualParticipantDeleted(it.key());
|
|
|
|
m_observerPositions.clear();
|
|
m_newObjectsWithoutParticipantIdSet.clear();
|
|
m_observerPlayerInstances.clear();
|
|
m_observerEnvironmentObjects.clear();
|
|
qDeleteAll(m_damageModelMap);
|
|
m_damageModelMap.clear();
|
|
|
|
m_enitityNumberCounter = 1; // restart
|
|
m_eventCount = 1;
|
|
}
|
|
|
|
bool NgsConnector::addHuman(const ParticipantInformation &participantData,
|
|
const rpr2::TacticalStatusStruct &state)
|
|
{
|
|
if (m_playerMap.contains(participantData.equipmentNo))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Startup"))
|
|
<< "addHuman("
|
|
<< participantData.equipmentNo << ", "
|
|
<< participantData.partyId << ", "
|
|
<< participantData.typeStruct.toString() << ", "
|
|
<< state.TacticalStatus << ")";
|
|
|
|
rpr2::IPlayerGuezHumanObjClass &player = m_somPlayer->getPlayerGuezHumanObjClass();
|
|
rpr2::IPlayerGuezHumanObjInstance *playerInstance = &player.newGuezHumanObjInstance();
|
|
|
|
DamageModel dm(state);
|
|
playerInstance->setDamageState(dm.damageState(-1));
|
|
playerInstance->setImmobilized(dm.immobilized(-1));
|
|
playerInstance->setFirePowerDisabled(dm.firePowerDisabled(-1));
|
|
playerInstance->setTacticalStatus(state);
|
|
|
|
return addPhysicalEntity(playerInstance, participantData);
|
|
}
|
|
|
|
bool NgsConnector::addObserverController(const ParticipantInformation &participantData)
|
|
{
|
|
if (m_playerMap.contains(participantData.equipmentNo))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Startup"))
|
|
<< "addObserverController("
|
|
<< participantData.equipmentNo << ", "
|
|
<< participantData.partyId << ", "
|
|
<< participantData.typeStruct.toString() << ")";
|
|
|
|
rpr2::IPlayerGuezObserverControllerObjClass &player = m_somPlayer->getPlayerGuezObserverControllerObjClass();
|
|
rpr2::IPlayerGuezObserverControllerObjInstance *playerInstance = &player.newGuezObserverControllerObjInstance();
|
|
|
|
return addPhysicalEntity(playerInstance, participantData);
|
|
}
|
|
|
|
bool NgsConnector::addGroundVehicle(const ParticipantInformation &participantData,
|
|
const rpr2::TacticalStatusStruct &state)
|
|
{
|
|
if (m_playerMap.contains(participantData.equipmentNo))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Startup"))
|
|
<< "addGroundVehicle("
|
|
<< participantData.equipmentNo << ", "
|
|
<< participantData.partyId << ", "
|
|
<< participantData.typeStruct.toString() << ", "
|
|
<< state.TacticalStatus << ")";
|
|
|
|
rpr2::IPlayerGuezGroundVehicleObjClass &player = m_somPlayer->getPlayerGuezGroundVehicleObjClass();
|
|
rpr2::IPlayerGuezGroundVehicleObjInstance *playerInstance = &player.newGuezGroundVehicleObjInstance();
|
|
|
|
DamageModel dm(state);
|
|
playerInstance->setDamageState(dm.damageState(-1));
|
|
playerInstance->setImmobilized(dm.immobilized(-1));
|
|
playerInstance->setFirePowerDisabled(dm.firePowerDisabled(-1));
|
|
playerInstance->setTacticalStatus(state);
|
|
|
|
return addPhysicalEntity(playerInstance, participantData);
|
|
}
|
|
|
|
bool NgsConnector::addBaseEntity(rpr2::IPlayerBaseEntityObjInstance *playerInstance,
|
|
const ParticipantInformation &participantData)
|
|
{
|
|
if (m_playerMap.contains(participantData.equipmentNo))
|
|
return false;
|
|
|
|
if (participantData.equipmentNo == 0)
|
|
return false;
|
|
|
|
IdentifierStruct is(participantData.equipmentNo);
|
|
|
|
m_playerMap.insert(participantData.equipmentNo, playerInstance);
|
|
|
|
playerInstance->setEntityType(participantData.typeStruct.toETS());
|
|
playerInstance->setEntityIdentifier(is.toEIS());
|
|
|
|
playerInstance->publish(getSimTime(participantData.position.msec));
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Startup")) << "Published Participant " << is.toString();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NgsConnector::addPhysicalEntity(rpr2::IPlayerPhysicalEntityObjInstance *playerInstance,
|
|
const ParticipantInformation &playerData)
|
|
{
|
|
rpr2::MarkingStruct ms = toMarkingStruct(playerData.designator);
|
|
playerInstance->setMarking(ms);
|
|
|
|
rpr2::ForceIdentifierEnum8::ET forceId = rpr2::ForceIdentifierEnum8::ET::Other; //// m_ngsHandler->ppmHandler()->forceIdentifierFromPartyId(playerData.partyId);
|
|
playerInstance->setForceIdentifier(forceId);
|
|
|
|
rpr2::SpatialStruct ss(spatialStructFromWorldLocation(playerData.position.toWorldLocation()));
|
|
|
|
playerInstance->setSpatial(ss);
|
|
|
|
return addBaseEntity(playerInstance, playerData);
|
|
}
|
|
|
|
bool NgsConnector::removeBaseEntity(int eqNo)
|
|
{
|
|
if (!m_playerMap.contains(eqNo))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.ShutDonw")) << "Participant " << eqNo << " removed.";
|
|
m_playerMap[eqNo]->deleteObjectInstance(getSimTime());
|
|
return (m_playerMap.remove(eqNo) > 0);
|
|
}
|
|
|
|
bool NgsConnector::setParticipantName(int eqNo, const QString &designator)
|
|
{
|
|
rpr2::IPlayerPhysicalEntityObjInstance *playerInstance = dynamic_cast<rpr2::IPlayerPhysicalEntityObjInstance *>(m_playerMap.value(eqNo, nullptr));
|
|
if (!playerInstance)
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Participant")) << "Participant " << eqNo << " changed MARKING to " << designator;
|
|
playerInstance->setMarking(toMarkingStruct(designator));
|
|
playerInstance->publish(getSimTime());
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::setParticipantForce(int eqNo, const rpr2::ForceIdentifierEnum8::ET forceIdentifier)
|
|
{
|
|
rpr2::IPlayerPhysicalEntityObjInstance *playerInstance = dynamic_cast<rpr2::IPlayerPhysicalEntityObjInstance *>(m_playerMap.value(eqNo, nullptr));
|
|
if (!playerInstance)
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Participant")) << "Participant " << eqNo << "changed FORCE to " << forceIdentifier;
|
|
playerInstance->setForceIdentifier(forceIdentifier);
|
|
playerInstance->publish(getSimTime());
|
|
return true;
|
|
}
|
|
|
|
// DDS -> HLA
|
|
//void NgsConnector::sendMunitionDetonation(const ParticipantPosition &pos, int chargeTypeId, rpr2::ForceIdentifierEnum8::ET forceId)
|
|
//{
|
|
// DEBUG_LOG(getLogger("NgsConnector.Outbound.MunitionDetonation"))
|
|
// << "Munition Detonation: "
|
|
// << "Location: " << pos.toString()
|
|
// << ", Charge Type: " << TypeStruct(getEtsCharge(chargeTypeId)).toString()
|
|
// << ", fired by Force " << forceId << " (Force unused)";
|
|
|
|
// rpr2::IPlayerMunitionDetonationIntClass &icx = m_somPlayer->getPlayerMunitionDetonationIntClass();
|
|
// rpr2::IPlayerMunitionDetonationIntInstance *icb = &icx.newMunitionDetonationIntInstance();
|
|
// icb->setDetonationLocation(pos.toWorldLocation());
|
|
// icb->setDetonationResultCode(rpr2::DetonationResultCodeEnum8::Detonation);
|
|
// icb->setEventIdentifier(getEventIdentifierStruct());
|
|
// // Todo: Ask Saab if and how we should encode the Party Id
|
|
// rpr2::RTIObjectIdStruct os;
|
|
// Q_UNUSED(forceId);
|
|
// os.ID = std::to_string(IdentifierStruct(0).toInt64()); // Own ExCon
|
|
// icb->setFiringObjectIdentifier(os);
|
|
// icb->setFuseType(rpr2::FuseTypeEnum16::Contact);
|
|
// icb->setMunitionType(getEtsCharge(chargeTypeId));
|
|
// icb->setQuantityFired(1);
|
|
// icb->setRateOfFire(0);
|
|
//// icb.setTargetObjectIdentifier("");
|
|
// icb->setWarheadType(rpr2::WarheadTypeEnum16::Kinetic);
|
|
// icb->publish(getSimTime(pos.msec));
|
|
//}
|
|
|
|
IdentifierStruct NgsConnector::getIdentifierStructbyEquipmentNo(const int eqId) const
|
|
{
|
|
const rpr2::IObserverBaseEntityObjInstance *beObject = nullptr;
|
|
|
|
if (m_observerPlayerInstances.contains(eqId))
|
|
beObject = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance *>(m_observerPlayerInstances[eqId]);
|
|
else if (m_playerMap.contains(eqId))
|
|
beObject = m_playerMap[eqId];
|
|
|
|
if (!beObject || !beObject->isValidEntityIdentifier())
|
|
return IdentifierStruct();
|
|
|
|
return IdentifierStruct(beObject->getEntityIdentifier());
|
|
}
|
|
|
|
void NgsConnector::sendParticipantInitRequest(const int eqId, bool resetManipulation, bool resetVulnerabilityState, bool restockCharges, qint64 simTimeMSecs)
|
|
{
|
|
IdentifierStruct is = getIdentifierStructbyEquipmentNo(eqId);
|
|
if (is.isNull() || is.isOwnElement())
|
|
return;
|
|
|
|
if (!resetVulnerabilityState)
|
|
{
|
|
WARNING_LOG(getLogger("NgsConnector.Outbound.GuezInit"))
|
|
<< "Request to "
|
|
<< (resetManipulation ? "reset Manipulation" : "")
|
|
<< (resetManipulation && restockCharges ? " and " : "")
|
|
<< (restockCharges ? "restock Charges" : "")
|
|
<< " without resetting the Player " << eqId << " to CombatReady. Not supported.";
|
|
return;
|
|
}
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.GuezInit"))
|
|
<< "Request to "
|
|
// << (resetManipulation ? "reset Manipulation" : "")
|
|
// << (resetManipulation && restockCharges ? " and " : "")
|
|
<< (restockCharges ? "restock Charges" : "")
|
|
<< " for Player " << eqId << " to Combat Ready. (Reset Manipulation is implicit for SAAB).";
|
|
|
|
rpr2::IPlayerGuezInitIntClass &icx = m_somPlayer->getPlayerGuezInitIntClass();
|
|
rpr2::IPlayerGuezInitIntInstance *icb = &icx.newGuezInitIntInstance();
|
|
|
|
icb->setActivateHelmetObservation(rpr2::ActivateHelmetObservationEnum8::NoChange);
|
|
icb->setEntityIdentifier(is.toEIS());
|
|
icb->setResetPlayer(restockCharges ? rpr2::ResetPlayerEnum8::CombatReadyWithReammunition : rpr2::ResetPlayerEnum8::CombatReadyWithoutReammunition);
|
|
icb->publish(getSimTime(simTimeMSecs));
|
|
}
|
|
|
|
void NgsConnector::sendParticipantBiteRequest(const int eqId, bool withSelfTest, qint64 simTimeMsecs)
|
|
{
|
|
IdentifierStruct is = getIdentifierStructbyEquipmentNo(eqId);
|
|
if (is.isNull() || is.isOwnElement())
|
|
return;
|
|
|
|
rpr2::IPlayerGuezRequestBiteReportIntClass &icx = m_somPlayer->getPlayerGuezRequestBiteReportIntClass();
|
|
rpr2::IPlayerGuezRequestBiteReportIntInstance *icb = &icx.newGuezRequestBiteReportIntInstance();
|
|
|
|
icb->setBiteReportType(withSelfTest ? rpr2::BiteReportTypeEnum8::StatusAfterSelftest : rpr2::BiteReportTypeEnum8::CurrentStatus);
|
|
icb->setEntityIdentifier(is.toEIS());
|
|
icb->publish(getSimTime(simTimeMsecs));
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.GuezBiteRequest"))
|
|
<< "Request for Bite Report for Player " << eqId << " with" << (withSelfTest ? "" : "out") << " selftest.";
|
|
}
|
|
|
|
bool NgsConnector::removeAesItem(int objId)
|
|
{
|
|
// get access
|
|
rpr2::IPlayerGuezMineFieldObjInstance *icb = dynamic_cast<rpr2::IPlayerGuezMineFieldObjInstance *>(m_environmentObjects.value(objId));
|
|
if (icb)
|
|
{
|
|
icb->deleteObjectInstance(); // ??? (ngs::SimTime(true));
|
|
m_environmentObjects.remove(objId);
|
|
// And we're done. Don't publish anything if called by startup.
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
bool NgsConnector::guezMineField(const WsTelegramMineFieldObject &data)
|
|
{
|
|
IdentifierStruct is ; //= IdentifierStruct::fromInt64(data.externalId());
|
|
|
|
const int objId = data.objectId; // assume unique
|
|
|
|
rpr2::IPlayerGuezMineFieldObjClass &ic = m_somPlayer->getPlayerGuezMineFieldObjClass();
|
|
|
|
// create/update:
|
|
rpr2::IPlayerGuezMineFieldObjInstance *icb = dynamic_cast<rpr2::IPlayerGuezMineFieldObjInstance *>(m_environmentObjects.value(objId));
|
|
if (!icb)
|
|
icb = &ic.newGuezMineFieldObjInstance();
|
|
|
|
// // Check for removed (now), then delete the item.
|
|
// if (icb &&
|
|
// (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsExpired ||
|
|
// data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved))
|
|
// {
|
|
// icb->deleteObjectInstance(ngs::SimTime(true));
|
|
// m_environmentObjects.remove(data.id());
|
|
// // And we're done. Don't publish anything if called by startup.
|
|
// return true;
|
|
// }
|
|
|
|
|
|
icb->setActivationTime(getClockTimeStruct(data.activationTime));
|
|
icb->setDuration(data.duration);
|
|
// icb->setMineType(getEtsCharge(data.chargeTypeId()));
|
|
// icb->setMineCount((data.density() - 0.1) / 0.008);
|
|
rpr2::ForceIdentifierEnum8::ET forceId = rpr2::ForceIdentifierEnum8::Other;
|
|
icb->setForceIdentifier(forceId);
|
|
// icb->setPointsData(positionArray(mineAreaSegment(segment, data.width(), data.density(), data.isCenterLine())));
|
|
// icb->setObjectType(dummyEOS());
|
|
// icb->publish(getSimTime(data.sampleTime()));
|
|
|
|
m_environmentObjects.insert(objId, icb);
|
|
return true;
|
|
}
|
|
|
|
|
|
//bool NgsConnector::setWorldLocation(int eqNo, const ParticipantPosition &pos, int eqNoHost)
|
|
//{
|
|
// rpr2::IPlayerPhysicalEntityObjInstance *playerInstance = dynamic_cast<rpr2::IPlayerPhysicalEntityObjInstance *>(m_playerMap.value(eqNo, nullptr));
|
|
// if (!playerInstance)
|
|
// return false;
|
|
|
|
// rpr2::SpatialStruct ss(spatialStructFromWorldLocation(pos.toWorldLocation()));
|
|
|
|
// rpr2::ConstituentPartRelationshipStruct cprs;
|
|
// cprs.Nature = rpr2::ConstituentPartNatureEnum16::Other;
|
|
// cprs.Position = rpr2::ConstituentPartPositionEnum16::Inside;
|
|
|
|
// rpr2::RTIObjectIdStruct rtiObjectIdHost;
|
|
|
|
// rpr2::RelativeRangeBearingStruct rrbs;
|
|
// rrbs.Bearing = 0.0;
|
|
// rrbs.Range = 0.0;
|
|
|
|
// // NGS Codegen does not automatically fill structure with 8 Bytes, when NamedLocationStruct is not defined with
|
|
// // a valid alternative:
|
|
|
|
// rpr2::NamedLocationStruct__StationName nlssn(rpr2::ConstituentPartStationNameEnum16::OnStationRangeBearing);
|
|
// nlssn.RelativeRangeAndBearing(rrbs);
|
|
|
|
// rpr2::NamedLocationStruct nlStruct;
|
|
// nlStruct.StationNumber = 0;
|
|
// nlStruct.StationName__A__Alternatives = nlssn;
|
|
|
|
// rpr2::EntityIdentifierStruct eis;
|
|
// eis.EntityNumber = 0;
|
|
// eis.FederateIdentifier.ApplicationID = 0;
|
|
// eis.FederateIdentifier.SiteID = 0;
|
|
|
|
// // Mounted?
|
|
// if (eqNoHost > 0)
|
|
// {
|
|
// // Get host from our players
|
|
// const rpr2::IObserverBaseEntityObjInstance *observerInstanceHost = m_playerMap.value(eqNoHost);
|
|
|
|
// // Not ours? Get from their players (our observed ones)
|
|
// if (!observerInstanceHost)
|
|
// observerInstanceHost = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance *>(m_observerPlayerInstances.value(eqNoHost));
|
|
|
|
// // If found and valid data, fill IsPartOf struct and apply to player
|
|
// if (observerInstanceHost && observerInstanceHost->isValidObjectName() && observerInstanceHost->isValidEntityIdentifier())
|
|
// {
|
|
// cprs.Position = rpr2::ConstituentPartPositionEnum16::Inside;
|
|
|
|
// rtiObjectIdHost.ID = observerInstanceHost->getObjectName();
|
|
// eis = observerInstanceHost->getEntityIdentifier();
|
|
// }
|
|
// }
|
|
|
|
// rpr2::IsPartOfStruct ipos;
|
|
// ipos.HostEntityIdentifier = eis;
|
|
// ipos.HostRTIObjectIdentifier = rtiObjectIdHost;
|
|
// ipos.NamedLocation = nlStruct;
|
|
// ipos.Relationship = cprs;
|
|
|
|
// playerInstance->setIsPartOf(ipos);
|
|
// playerInstance->setSpatial(ss);
|
|
// playerInstance->publish(getSimTime(pos.msec));
|
|
// DEBUG_LOG(getLogger("NgsConnector.Outbound.Player.Position"))
|
|
// << "Player: " << eqNo << ", Position: " << pos.toString() << ", Time: " << pos.msec << ", Mounted on: " << eqNoHost;
|
|
|
|
// return true;
|
|
//}
|
|
|
|
ngs::SimTime NgsConnector::getSimTime(qint64 msecsSinceEpoch)
|
|
{
|
|
if (msecsSinceEpoch == 0)
|
|
msecsSinceEpoch = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
|
|
return ngs::SimTime(msecsSinceEpoch / 1000, (msecsSinceEpoch % 1000) * 1000);
|
|
}
|
|
|
|
ngs::SimTime NgsConnector::getSimTime(const QDateTime &dateTime)
|
|
{
|
|
return getSimTime(dateTime.toMSecsSinceEpoch());
|
|
}
|
|
|
|
void NgsConnector::go()
|
|
{
|
|
if (!m_somPlayer)
|
|
return;
|
|
|
|
try
|
|
{
|
|
m_somPlayer->go(ngs::IObserver::GOSTEP);
|
|
}
|
|
catch (const NGSException &ex)
|
|
{
|
|
ERROR_LOG(m_logger) << "NGS Exception caught in Event Loop" << ex.print();
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
ERROR_LOG(m_logger) << "Standard Exception caught in Event Loop: " << e.what();
|
|
}
|
|
catch (...)
|
|
{
|
|
// ERROR_LOG(m_logger) << "Generic Exception caught in Event Loop";
|
|
}
|
|
}
|
|
|
|
void NgsConnector::onFirstTickFinished()
|
|
{
|
|
unsubscribeFromNgs();
|
|
m_bCanPublishData = true;
|
|
subscribeAtNgs();
|
|
emit firstTickFinished();
|
|
}
|
|
|
|
void NgsConnector::connectObserverObjectSignals(ObserverObjectCB *entity)
|
|
{
|
|
connect(entity, &ObserverObjectCB::newObjectInstance2,
|
|
this, &NgsConnector::addObserverObjectInstance, Qt::UniqueConnection);
|
|
connect(entity, &ObserverObjectCB::objectInstanceDeleted,
|
|
this, &NgsConnector::removeObserverObjectInstance, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverBaseEntityObjectSignals(ObserverBaseEntityObjectCB *entity)
|
|
{
|
|
connectObserverObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverBaseEntityObjectCB::entityIdentifierChanged,
|
|
this, &NgsConnector::onEntityIdentifierChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverBaseEntityObjectCB::spatialChanged,
|
|
this, &NgsConnector::onSpatialChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverBaseEntityObjectCB::entityTypeChanged,
|
|
this, &NgsConnector::onEntityTypeChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverBaseEntityObjectCB::isPartOfChanged,
|
|
this, &NgsConnector::onIsPartOfChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverPhysicalEntityObjectSignals(ObserverPhysicalEntityObjectCB *entity)
|
|
{
|
|
connectObserverBaseEntityObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverPhysicalEntityObjectCB::markingChanged,
|
|
this, &NgsConnector::onMarkingChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverPhysicalEntityObjectCB::forceIdentifierChanged,
|
|
this, &NgsConnector::onForceIdentifierChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverPlatformObjectSignals(ObserverPlatformObjectCB *entity)
|
|
{
|
|
connectObserverPhysicalEntityObjectSignals(entity);
|
|
|
|
// No extra signals
|
|
}
|
|
|
|
void NgsConnector::connectObserverGroundVehicleObjectSignals(ObserverGroundVehicleObjectCB *entity)
|
|
{
|
|
connectObserverPlatformObjectSignals(entity);
|
|
|
|
// No extra signals
|
|
}
|
|
|
|
void NgsConnector::connectObserverGuezGroundVehicleObjectSignals(ObserverGuezGroundVehicleObjectCB *entity)
|
|
{
|
|
connectObserverGroundVehicleObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverGuezGroundVehicleObjectCB::tacticalStatusChanged,
|
|
this, &NgsConnector::onTacticalStatusChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverLifeformObjectSignals(ObserverLifeformObjectCB *entity)
|
|
{
|
|
connectObserverPhysicalEntityObjectSignals(entity);
|
|
|
|
// No extra signals
|
|
}
|
|
|
|
|
|
void NgsConnector::connectObserverHumanObjectSignals(ObserverHumanObjectCB *entity)
|
|
{
|
|
connectObserverLifeformObjectSignals(entity);
|
|
|
|
// No extra signals
|
|
}
|
|
|
|
void NgsConnector::connectObserverGuezHumanObjectSignals(ObserverGuezHumanObjectCB *entity)
|
|
{
|
|
connectObserverHumanObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverGuezHumanObjectCB::tacticalStatusChanged,
|
|
this, &NgsConnector::onTacticalStatusChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverGuezObserverControllerObjectSignals(ObserverGuezObserverControllerObjectCB *entity)
|
|
{
|
|
connectObserverHumanObjectSignals(entity);
|
|
|
|
// No extra signals
|
|
}
|
|
|
|
void NgsConnector::connectObserverEnvironmentObjectObjectSignals(ObserverEnvironmentObjectObjectCB *entity)
|
|
{
|
|
connectObserverObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverEnvironmentObjectObjectCB::objectIdentifierChanged,
|
|
this, &NgsConnector::onObjectIdentifierChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverEnvironmentObjectObjectCB::forceIdentifierChangedEO,
|
|
this, &NgsConnector::onForceIdentifierChangedEO, Qt::UniqueConnection);
|
|
connect(entity, &ObserverEnvironmentObjectObjectCB::spatialChanged,
|
|
this, &NgsConnector::onSpatialChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverArealObjectObjectSignals(ObserverArealObjectObjectCB *entity)
|
|
{
|
|
connectObserverEnvironmentObjectObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverArealObjectObjectCB::pointsDataChanged,
|
|
this, &NgsConnector::onPointsDataChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverArealObjectObjectCB::percentCompleteChanged,
|
|
this, &NgsConnector::onPercentCompleteChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverArealObjectObjectCB::deactivatedChanged,
|
|
this, &NgsConnector::onDeactivatedChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverPointObjectObjectSignals(ObserverPointObjectObjectCB *entity)
|
|
{
|
|
connectObserverEnvironmentObjectObjectSignals(entity);
|
|
}
|
|
|
|
void NgsConnector::connectObserverOtherArealObjectObjectSignals(ObserverOtherArealObjectObjectCB *entity)
|
|
{
|
|
connectObserverArealObjectObjectSignals(entity);
|
|
}
|
|
|
|
void NgsConnector::connectObserverOtherPointObjectObjectSignals(ObserverOtherPointObjectObjectCB *entity)
|
|
{
|
|
connectObserverPointObjectObjectSignals(entity);
|
|
}
|
|
|
|
void NgsConnector::connectObserverGuezMineFieldObjectSignals(ObserverGuezMineFieldObjectCB *entity)
|
|
{
|
|
connectObserverOtherArealObjectObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverGuezMineFieldObjectCB::areaEffectSimulationNameChanged,
|
|
this, &NgsConnector::onAreaEffectSimulationNameChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverGuezMineFieldObjectCB::activationTimeChanged,
|
|
this, &NgsConnector::onActivationTimeChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverGuezMineFieldObjectCB::durationChanged,
|
|
this, &NgsConnector::onDurationChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverGuezMineFieldObjectCB::mineTypeChanged,
|
|
this, &NgsConnector::onMineTypeChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::connectObserverGuezMineFieldBreachObjectSignals(ObserverGuezMineFieldBreachObjectCB *entity)
|
|
{
|
|
connectObserverOtherArealObjectObjectSignals(entity);
|
|
|
|
connect(entity, &ObserverGuezMineFieldBreachObjectCB::areaEffectSimulationNameChanged,
|
|
this, &NgsConnector::onAreaEffectSimulationNameChanged, Qt::UniqueConnection);
|
|
connect(entity, &ObserverGuezMineFieldBreachObjectCB::activationTimeChanged,
|
|
this, &NgsConnector::onActivationTimeChanged, Qt::UniqueConnection);
|
|
}
|
|
|
|
void NgsConnector::addObserverObjectInstance(const ngs::IObserverObjectInstance &obj)
|
|
{
|
|
// Put it into the Observer list later on, when the slot "onEntityIdentifierChanged()" is called
|
|
// Then we can be sure, the EntityIdentifier is definetely set.
|
|
const rpr2::IObserverBaseEntityObjInstance *beObject = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance *>(&obj);
|
|
if (beObject && beObject->isValidEntityIdentifier())
|
|
{
|
|
IdentifierStruct is(beObject->getEntityIdentifier());
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << is.toString() << " added.";
|
|
m_newObjectsWithoutParticipantIdSet.insert(&obj);
|
|
onEntityIdentifierChanged(beObject->getEntityIdentifier(), beObject);
|
|
}
|
|
|
|
const rpr2::IObserverEnvironmentObjectObjInstance *eoObject = dynamic_cast<const rpr2::IObserverEnvironmentObjectObjInstance *>(&obj);
|
|
if (eoObject && eoObject->isValidObjectIdentifier())
|
|
{
|
|
IdentifierStruct is(eoObject->getObjectIdentifier());
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " added.";
|
|
m_newObjectsWithoutParticipantIdSet.insert(&obj);
|
|
onObjectIdentifierChanged(eoObject->getObjectIdentifier(), eoObject);
|
|
}
|
|
}
|
|
|
|
void NgsConnector::removeObserverObjectInstance(const ngs::IObserverObjectInstance &obj)
|
|
{
|
|
const rpr2::IObserverBaseEntityObjInstance *beObject = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance *>(&obj);
|
|
const rpr2::IObserverEnvironmentObjectObjInstance *eoObject = dynamic_cast<const rpr2::IObserverEnvironmentObjectObjInstance *>(&obj);
|
|
|
|
IdentifierStruct is;
|
|
if (beObject && beObject->isValidEntityIdentifier())
|
|
{
|
|
is = IdentifierStruct(beObject->getEntityIdentifier());
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player")) << "Player: " << is.toString() << " removed.";
|
|
}
|
|
else if (eoObject && eoObject->isValidObjectIdentifier())
|
|
{
|
|
is = IdentifierStruct(eoObject->getObjectIdentifier());
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object")) << "Object: " << is.toString() << " removed.";
|
|
}
|
|
else
|
|
return;
|
|
|
|
if (is.isOwnElement())
|
|
{
|
|
// TODO: handle signal
|
|
emit virtualParticipantDeleted(is.entityNumber());
|
|
}
|
|
|
|
// really neccessary?
|
|
//int *ptr = static_cast<int *>(obj.getUserObjectID());
|
|
//delete[] ptr;
|
|
|
|
m_newObjectsWithoutParticipantIdSet.remove(&obj);
|
|
|
|
if (beObject)
|
|
{
|
|
m_observerPlayerInstances.remove(is.entityNumber());
|
|
auto it = m_damageModelMap.find(is.entityNumber());
|
|
if (it != m_damageModelMap.end())
|
|
{
|
|
delete it.value();
|
|
m_damageModelMap.erase(it);
|
|
}
|
|
}
|
|
|
|
if (eoObject)
|
|
{
|
|
m_observerEnvironmentObjects.remove(is.entityNumber());
|
|
emit aesRemoveItem(is.toInt64());
|
|
}
|
|
|
|
}
|
|
|
|
void NgsConnector::ensureDamageModelExists(const IdentifierStruct &is)
|
|
{
|
|
if (m_damageModelMap.contains(is.entityNumber()))
|
|
return;
|
|
|
|
DamageModel *dmgModel(new DamageModel(is));
|
|
// connect(dmgModel, &DamageModel::damageStateChanged,
|
|
// this, &NgsConnector::onDamageStateChangedTimeout);
|
|
connect(dmgModel, &DamageModel::playerManipulationChanged,
|
|
this, &NgsConnector::playerManipulationChanged);
|
|
m_damageModelMap.insert(is.entityNumber(), dmgModel);
|
|
}
|
|
|
|
rpr2::MarkingStruct NgsConnector::toMarkingStruct(const QString &designator)
|
|
{
|
|
rpr2::MarkingStruct ms;
|
|
const QString string = designator.leftJustified(ms.MarkingData.size(), QLatin1Char('\0'), true);
|
|
const QByteArray ba = string.toUtf8();
|
|
for (size_t i = 0; i < ms.MarkingData.size(); ++i)
|
|
ms.MarkingData[i] = ba.at(i);
|
|
// this is wrong but there is no 'UTF8' ...
|
|
ms.MarkingEncodingType = rpr2::MarkingEncodingEnum8::ASCII;
|
|
return ms;
|
|
}
|
|
|
|
rpr2::ClockTimeStruct NgsConnector::getClockTimeStruct(qint64 msecsSinceEpoch)
|
|
{
|
|
// Todo: Wrong!
|
|
rpr2::ClockTimeStruct cts;
|
|
// New:
|
|
// cts.Hours = msecsSinceEpoch / (1000LL * 60 * 60);
|
|
// qint64 msecsAfterTheHour = msecsSinceEpoch - (cts.Hours * 1000 * 60 * 60);
|
|
// double portionOfAnHour = msecsAfterTheHour / (1000 * 60 * 60);
|
|
// cts.TimePastTheHour = lrint(portionOfAnHour * (2LL<<31);
|
|
cts.Hours = msecsSinceEpoch / (1000 * 60 * 60);
|
|
cts.TimePastTheHour = msecsSinceEpoch - (cts.Hours * 1000 * 60 * 60) ; // This is wrong!
|
|
return cts;
|
|
}
|
|
|
|
qint64 NgsConnector::getMSecsSinceEpoch(const rpr2::ClockTimeStruct &cts)
|
|
{
|
|
// Todo: Wrong!
|
|
qint64 time = 0;
|
|
time += (1000LL * 60 * 60 * cts.Hours);
|
|
time += cts.TimePastTheHour; // Contains MSecs at the moment
|
|
// New:
|
|
// time += 1000LL * 60 * 60 * (cts.TimePastTheHour / (2LL<<31)) ;
|
|
return time;
|
|
}
|
|
|
|
//rpr2::EntityTypeStruct NgsConnector::getEtsCharge(int chargeType) const
|
|
//{
|
|
// const auto ct = m_ngsHandler->ppmHandler()->chargeTypeFromId(chargeType);
|
|
// if (ct.disEntity().size() == 0)
|
|
// return TypeStruct::fromString(QLatin1String("2.0.0.0.0.0.1")).toETS(); // Default
|
|
// return TypeStruct::fromString(QString::fromStdString(ct.disEntity())).toETS();
|
|
//}
|
|
|
|
template<typename T>
|
|
rpr2::ArrayOfWorldLocationStructDynamicHLAlengthlessVarArray NgsConnector::positionArray(const T &data)
|
|
{
|
|
rpr2::ArrayOfWorldLocationStructDynamicHLAlengthlessVarArray positions;
|
|
if (data.size() == 0)
|
|
return positions;
|
|
|
|
positions.resize(data.size());
|
|
unsigned int i = 0;
|
|
for (const auto &item : data)
|
|
positions[i++] = ParticipantPosition(item).toWorldLocation();
|
|
|
|
return positions;
|
|
}
|
|
|
|
//QPolygonF NgsConnector::mineCorridorSegment(const Core::GeoPosition2D &start, const Core::GeoPosition2D &end, double width)
|
|
//{
|
|
// QPointF startPoint(start.lon(), start.lat());
|
|
// QPointF endPoint(end.lon(), end.lat());
|
|
// LtsCoordTrans::UtmCoordinate startPositionUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(startPoint);
|
|
|
|
// LtsCoordTrans::UtmCoordinate endPositionUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(endPoint, startPositionUtm.zone);
|
|
|
|
// QLineF lengthVector(QPointF(startPositionUtm.x, startPositionUtm.y),
|
|
// QPointF(endPositionUtm.x, endPositionUtm.y));
|
|
|
|
// QPolygonF segment = QPolygonF({QPointF(0, width),
|
|
// QPointF(lengthVector.length(), width),
|
|
// QPointF(lengthVector.length(), 0),
|
|
// QPointF(0, 0)
|
|
// });
|
|
|
|
// segment.translate(QPointF(0, -(width / 2)));
|
|
|
|
// segment = fromRotation(0 - lengthVector.angle()).map(segment);
|
|
|
|
// return utmToGeogrphic(segment, startPositionUtm);
|
|
//}
|
|
|
|
|
|
template <class T>
|
|
static inline T compass2rad(T degree)
|
|
{
|
|
static_assert(!std::is_integral<T>::value, "Floating Point Value Required! Integer may be in Centidegree?!?");
|
|
return (M_PI / 2.0) - (degree * M_PI / 180.0);
|
|
}
|
|
|
|
template <class T>
|
|
static inline T deg2rad(T degree)
|
|
{
|
|
static_assert(!std::is_integral<T>::value, "Floating Point Value Required! Integer may be in Centidegree?!?");
|
|
return degree * M_PI / 180.0;
|
|
}
|
|
|
|
//QPolygonF NgsConnector::nContamination(const AreaEffectSimulation::NContamination &awf)
|
|
//{
|
|
// // Special Case: BorderLengthInner == 0
|
|
// LtsCoordTrans::UtmCoordinate impactPositionUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(awf.impactPosition().lon(), awf.impactPosition().lat());
|
|
// if (qFuzzyIsNull(awf.borderLengthInner()))
|
|
// {
|
|
// if (!qFuzzyIsNull(awf.borderLengthOuter()))
|
|
// return QPolygonF();
|
|
// QPolygonF poly;
|
|
// poly.reserve(8);
|
|
// for (int i = 0; i < 360; i += 45)
|
|
// {
|
|
// double angle = compass2rad(double(i));
|
|
// poly << impactPositionUtm.geographic(QPointF(cos(angle) * awf.impactRadius(), sin(angle) * awf.impactRadius()));
|
|
// }
|
|
// return poly;
|
|
// }
|
|
// if (awf.impactRadius() > awf.borderLengthInner())
|
|
// return QPolygonF();
|
|
|
|
// double halfSpanAngleRad = deg2rad(awf.spanAngle()) / 2.0; // Angle between MCC and MCT at C
|
|
// double acos_val = awf.impactRadius() / awf.borderLengthInner(); // Adjacent / Hypotenuse (Angle between SCT and MCT at C)
|
|
// double scAngleRad = acos(acos_val) + halfSpanAngleRad; // Thus, Angle between MCC and SCT at C. ("Small Circle Angle")
|
|
|
|
// // Calculate Points:
|
|
// QPointF sct(cos(scAngleRad) * awf.impactRadius(), sin(scAngleRad) * awf.impactRadius());
|
|
// QPointF scb(cos(scAngleRad) * awf.impactRadius(), -sin(scAngleRad) * awf.impactRadius());
|
|
|
|
// QPointF mct(cos(halfSpanAngleRad) * (awf.borderLengthInner()), sin(halfSpanAngleRad) * (awf.borderLengthInner()));
|
|
// QPointF mcb(cos(halfSpanAngleRad) * (awf.borderLengthInner()), -sin(halfSpanAngleRad) * (awf.borderLengthInner()));
|
|
|
|
// QPointF bct(cos(halfSpanAngleRad) * (awf.borderLengthInner() + awf.borderLengthOuter()),
|
|
// sin(halfSpanAngleRad) * (awf.borderLengthInner() + awf.borderLengthOuter()));
|
|
// QPointF bcb(cos(halfSpanAngleRad) * (awf.borderLengthInner() + awf.borderLengthOuter()),
|
|
// -sin(halfSpanAngleRad) * (awf.borderLengthInner() + awf.borderLengthOuter()));
|
|
|
|
// QPolygonF polyUtm;
|
|
// polyUtm.reserve(8);
|
|
|
|
// polyUtm << sct;
|
|
// polyUtm << mct;
|
|
// polyUtm << bct; // In For
|
|
// polyUtm << QPointF(awf.borderLengthInner() + awf.borderLengthOuter(), 0);
|
|
// polyUtm << bcb; // May not be in for, if (spanAngle % steps != 0)
|
|
// polyUtm << mcb;
|
|
// polyUtm << scb; // In For
|
|
// polyUtm << QPointF(-awf.impactRadius(), 0);
|
|
|
|
|
|
// polyUtm = fromRotation(90.0 - awf.rotationAngle()).map(polyUtm); // The cunstructed poly ist heading eastwards but must be rotated as from north
|
|
|
|
// const QPolygonF poly(utmToGeogrphic(polyUtm, impactPositionUtm));
|
|
// return poly;
|
|
//}
|
|
|
|
//std::vector<Core::GeoPosition> NgsConnector::bcReduction(const std::vector<Core::GeoPosition> &form)
|
|
//{
|
|
// std::vector<Core::GeoPosition> vec;
|
|
// vec.resize(8);
|
|
// if (form.size() == 72) // 0, 45, 90, 135, 180, 225, 270, 315° (Kreis!)
|
|
// {
|
|
// vec[0] = form[0];
|
|
// vec[1] = form[9];
|
|
// vec[2] = form[18];
|
|
// vec[3] = form[27];
|
|
// vec[4] = form[36];
|
|
// vec[5] = form[45];
|
|
// vec[6] = form[54];
|
|
// vec[7] = form[63];
|
|
// }
|
|
// else if (form.size() == 74) // 0, 60, 120, 180° (rechts), 180, 240, 300, 360° (links) (Wurscht!)
|
|
// {
|
|
// vec[0] = form[0];
|
|
// vec[1] = form[12];
|
|
// vec[2] = form[24];
|
|
// vec[3] = form[36];
|
|
// vec[4] = form[37];
|
|
// vec[5] = form[49];
|
|
// vec[6] = form[61];
|
|
// vec[7] = form[73];
|
|
// }
|
|
// return vec;
|
|
//}
|
|
rpr2::ArrayOfHLAoctetN_slsh_AperfectalwaysN_slsh_ADynamicHLApaddingTo32Array NgsConnector::triggeredImpactsArray(const std::vector<uint8_t> &data)
|
|
{
|
|
rpr2::ArrayOfHLAoctetN_slsh_AperfectalwaysN_slsh_ADynamicHLApaddingTo32Array impacts;
|
|
if (data.size() == 0)
|
|
return impacts;
|
|
|
|
impacts.resize(data.size());
|
|
unsigned int i = 0;
|
|
for (const auto &item : data)
|
|
impacts[i++] = static_cast<ngs::CHAR8>(item);
|
|
|
|
return impacts;
|
|
}
|
|
|
|
rpr2::HitResultEnum16::ET NgsConnector::getHitResultEnum(const ProjectDataManagement::VulnerabilityState &ts)
|
|
{
|
|
switch (ts.underlying())
|
|
{
|
|
case ProjectDataManagement::VulnerabilityState_def::CombatReady:
|
|
return rpr2::HitResultEnum16::Reset;
|
|
case ProjectDataManagement::VulnerabilityState_def::LightDamage:
|
|
return rpr2::HitResultEnum16::LightDamage;
|
|
case ProjectDataManagement::VulnerabilityState_def::MediumDamage:
|
|
return rpr2::HitResultEnum16::MediumDamage;
|
|
case ProjectDataManagement::VulnerabilityState_def::HeavyDamage:
|
|
return rpr2::HitResultEnum16::HeavyDamage;
|
|
case ProjectDataManagement::VulnerabilityState_def::MobilityKill:
|
|
return rpr2::HitResultEnum16::MobilityKill;
|
|
case ProjectDataManagement::VulnerabilityState_def::VisibleMobilityKill:
|
|
return rpr2::HitResultEnum16::MobilityKillVisible;
|
|
case ProjectDataManagement::VulnerabilityState_def::WeaponSystemDamage:
|
|
return rpr2::HitResultEnum16::WeaponDamage;
|
|
case ProjectDataManagement::VulnerabilityState_def::VisibleWeaponSystemDamage:
|
|
return rpr2::HitResultEnum16::WeaponDamageVisible;
|
|
case ProjectDataManagement::VulnerabilityState_def::CatastrophicKill:
|
|
return rpr2::HitResultEnum16::TotalKill;
|
|
case ProjectDataManagement::VulnerabilityState_def::TemporarySeverance:
|
|
return rpr2::HitResultEnum16::TemporaryFailure;
|
|
case ProjectDataManagement::VulnerabilityState_def::NearMiss:
|
|
return rpr2::HitResultEnum16::NearMiss;
|
|
case ProjectDataManagement::VulnerabilityState_def::HitWithNoEffect:
|
|
return rpr2::HitResultEnum16::HitWithNoEffect;
|
|
case ProjectDataManagement::VulnerabilityState_def::NContamination:
|
|
case ProjectDataManagement::VulnerabilityState_def::BContamination:
|
|
case ProjectDataManagement::VulnerabilityState_def::CContamination:
|
|
return rpr2::HitResultEnum16::Contaminated;
|
|
default:
|
|
return rpr2::HitResultEnum16::Reset;
|
|
}
|
|
return rpr2::HitResultEnum16::Reset;
|
|
}
|
|
|
|
ProjectDataManagement::VulnerabilityState NgsConnector::getTacticalStatusEnum(const rpr2::HitResultEnum16::ET &hr)
|
|
{
|
|
switch (hr)
|
|
{
|
|
case rpr2::HitResultEnum16::Reset:
|
|
return ProjectDataManagement::VulnerabilityState_def::CombatReady;
|
|
case rpr2::HitResultEnum16::LightDamage:
|
|
return ProjectDataManagement::VulnerabilityState_def::LightDamage;
|
|
case rpr2::HitResultEnum16::MediumDamage:
|
|
return ProjectDataManagement::VulnerabilityState_def::MediumDamage;
|
|
case rpr2::HitResultEnum16::HeavyDamage:
|
|
return ProjectDataManagement::VulnerabilityState_def::HeavyDamage;
|
|
case rpr2::HitResultEnum16::MobilityKill:
|
|
return ProjectDataManagement::VulnerabilityState_def::MobilityKill;
|
|
case rpr2::HitResultEnum16::MobilityKillVisible:
|
|
return ProjectDataManagement::VulnerabilityState_def::VisibleMobilityKill;
|
|
case rpr2::HitResultEnum16::WeaponDamage:
|
|
return ProjectDataManagement::VulnerabilityState_def::WeaponSystemDamage;
|
|
case rpr2::HitResultEnum16::WeaponDamageVisible:
|
|
return ProjectDataManagement::VulnerabilityState_def::VisibleWeaponSystemDamage;
|
|
case rpr2::HitResultEnum16::TotalKill:
|
|
return ProjectDataManagement::VulnerabilityState_def::CatastrophicKill;
|
|
case rpr2::HitResultEnum16::CheatingKill:
|
|
return ProjectDataManagement::VulnerabilityState_def::CatastrophicKill;
|
|
case rpr2::HitResultEnum16::NearMiss:
|
|
return ProjectDataManagement::VulnerabilityState_def::NearMiss;
|
|
case rpr2::HitResultEnum16::HitWithNoEffect:
|
|
return ProjectDataManagement::VulnerabilityState_def::HitWithNoEffect;
|
|
case rpr2::HitResultEnum16::Contaminated:
|
|
return ProjectDataManagement::VulnerabilityState_def::CContamination;
|
|
case rpr2::HitResultEnum16::TemporaryFailure:
|
|
return ProjectDataManagement::VulnerabilityState_def::TemporarySeverance;
|
|
default:
|
|
return ProjectDataManagement::VulnerabilityState_def::NoChange;
|
|
}
|
|
return ProjectDataManagement::VulnerabilityState_def::NoChange;
|
|
}
|
|
|
|
QPolygonF NgsConnector::utmToGeogrphic(const QPolygonF &polyUtm, const LtsCoordTrans::UtmCoordinate &base)
|
|
{
|
|
QPolygonF poly;
|
|
poly.reserve(polyUtm.size());
|
|
for (const QPointF &point : qAsConst(polyUtm))
|
|
poly << base.geographic(point);
|
|
return poly;
|
|
}
|
|
|
|
void NgsConnector::onEntityIdentifierChanged(const rpr2::EntityIdentifierStruct &eis,
|
|
const rpr2::IObserverBaseEntityObjInstance *obj)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
// Own players are irrelevant here
|
|
if (is.isOwnElement())
|
|
{
|
|
m_newObjectsWithoutParticipantIdSet.remove(obj);
|
|
return;
|
|
}
|
|
|
|
// We cannot do anything here then. Who was it before?
|
|
if (m_observerPlayerInstances.contains(is.entityNumber()))
|
|
return;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << is.toString() << " will be added.";
|
|
|
|
m_observerPlayerInstances.insert(is.entityNumber(), obj);
|
|
m_newObjectsWithoutParticipantIdSet.remove(obj);
|
|
|
|
|
|
GuezHitStruct hs;
|
|
hs.originatorType = ProjectDataManagement::StateChangeOriginator_def::Initialization;
|
|
hs.sampleTime = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(); // We don't have anything better
|
|
hs.targetId = is.entityNumber();
|
|
hs.vulnerabilityState = ProjectDataManagement::VulnerabilityState_def::VulnerabilityBitsChanged; // --> Evaluate State from Bits (done in PPM Service).
|
|
|
|
QTimer::singleShot(STATUS_WAIT_INTERVAL, this, [this, hs, obj]() mutable
|
|
{
|
|
auto ptr = m_damageModelMap.value(hs.targetId);
|
|
if (!ptr)
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Damage State of entity " << hs.targetId
|
|
<< " didn't exist 50msecs after EntityIdentifier Changed. Setting Initial Status not possible!";
|
|
return;
|
|
}
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << hs.targetId << ". Setting initial Status, initial Position and Manipulation.";
|
|
|
|
const auto vulnerabilityBits = ptr->totalState(hs.sampleTime);
|
|
hs.vulnerabilityBits = (vulnerabilityBits & ~rpr2::TotalStatusEnum32::Manipulation);
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.Status"))
|
|
<< "Player: " << hs.targetId
|
|
<< " New Total Status: " << hs.vulnerabilityBits;
|
|
emit guezHit(hs);
|
|
|
|
ParticipantPosition pos(obj->getSpatial().DeadReckoningAlgorithm__A__Alternatives.SpatialStatic().WorldLocation);
|
|
long time = obj->getLatestTimeStamp().getSeconds() * 1000;
|
|
if (time == 0)
|
|
time = getSimTime().getSeconds() * 1000;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.Position"))
|
|
<< "Player: " << hs.targetId << ", Initial Position: " << pos.toString() << ", Time: " << pos.msec;
|
|
|
|
emit spatialChanged(hs.targetId, pos, time);
|
|
|
|
// That may be too much but better safe than sorry...
|
|
// TODO: set to DamageModel, use emit from there?
|
|
emit playerManipulationChanged(hs.targetId, vulnerabilityBits & rpr2::TotalStatusEnum32::Manipulation, hs.sampleTime);
|
|
|
|
});
|
|
}
|
|
|
|
bool NgsConnector::onObjectIdentifierChanged(const rpr2::EntityIdentifierStruct &eis,
|
|
const rpr2::IObserverEnvironmentObjectObjInstance *obj)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
// Own players are irrelevant here
|
|
if (is.isOwnElement())
|
|
{
|
|
m_newObjectsWithoutParticipantIdSet.remove(obj);
|
|
return false;
|
|
}
|
|
|
|
// Already created -> ignore
|
|
if (m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return true;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " will be added.";
|
|
|
|
m_observerEnvironmentObjects.insert(is.entityNumber(), obj);
|
|
m_nonpublishedEnvironmentObjects.insert(is.entityNumber());
|
|
m_newObjectsWithoutParticipantIdSet.remove(obj);
|
|
|
|
const rpr2::IObserverGuezMineFieldObjInstance *minefield = dynamic_cast<const rpr2::IObserverGuezMineFieldObjInstance *>(obj);
|
|
if (minefield)
|
|
return addMinefield(minefield);
|
|
|
|
const rpr2::IObserverGuezMineFieldBreachObjInstance *minefieldBreach = dynamic_cast<const rpr2::IObserverGuezMineFieldBreachObjInstance *>(obj);
|
|
if (minefieldBreach)
|
|
return addMinefieldBreach(minefieldBreach);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool getCorridorSegment(const rpr2::ArrayOfWorldLocationStructDynamicHLAlengthlessVarArray &pointsDataIn,
|
|
std::vector<Core::GeoPosition2D> &segmentsOut,
|
|
double &widthOut)
|
|
{
|
|
// P0 P3
|
|
// L *-------------------* L
|
|
// i | | i
|
|
// n * S0 S1 * n
|
|
// e | | e
|
|
// 1 *-------------------* 2
|
|
// P1 P2
|
|
|
|
// Calculate width = P0->P1
|
|
// Calculate S0, S1
|
|
|
|
if (pointsDataIn.size() != 4)
|
|
return false;
|
|
|
|
ParticipantPosition p0(pointsDataIn[0]);
|
|
ParticipantPosition p1(pointsDataIn[1]);
|
|
ParticipantPosition p2(pointsDataIn[2]);
|
|
ParticipantPosition p3(pointsDataIn[3]);
|
|
|
|
LtsCoordTrans::UtmCoordinate utmP0 = LtsCoordTrans::UtmCoordinate::fromGeographic(p0.toPoint());
|
|
LtsCoordTrans::UtmCoordinate utmP1 = LtsCoordTrans::UtmCoordinate::fromGeographic(p1.toPoint(), utmP0.zone);
|
|
LtsCoordTrans::UtmCoordinate utmP2 = LtsCoordTrans::UtmCoordinate::fromGeographic(p2.toPoint(), utmP0.zone);
|
|
LtsCoordTrans::UtmCoordinate utmP3 = LtsCoordTrans::UtmCoordinate::fromGeographic(p3.toPoint(), utmP0.zone);
|
|
|
|
QLineF line1(utmP0.x, utmP0.y, utmP1.x, utmP1.y);
|
|
widthOut = line1.length();
|
|
line1.setLength(0.5 * line1.length());
|
|
|
|
LtsCoordTrans::UtmCoordinate utmS0(utmP0.zone, line1.p2().x(), line1.p2().y(), utmP0.northp);
|
|
|
|
QLineF line2(utmP2.x, utmP2.y, utmP3.x, utmP3.y);
|
|
widthOut = line2.length();
|
|
line2.setLength(0.5 * line2.length());
|
|
|
|
LtsCoordTrans::UtmCoordinate utmS1(utmP0.zone, line2.p2().x(), line2.p2().y(), utmP0.northp);
|
|
|
|
segmentsOut.resize(2);
|
|
segmentsOut[0] = Core::GeoPosition2D(utmS0.geographic().x(), utmS0.geographic().y());
|
|
segmentsOut[1] = Core::GeoPosition2D(utmS1.geographic().x(), utmS1.geographic().y());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::addMinefield(const rpr2::IObserverGuezMineFieldObjInstance *minefield)
|
|
{
|
|
return false;
|
|
|
|
/*
|
|
int id = minefield->isValidObjectIdentifier() ? IdentifierStruct(minefield->getObjectIdentifier()).entityNumber() : 0;
|
|
QTimer::singleShot(STATUS_WAIT_INTERVAL, this, [this, minefield, id]() mutable
|
|
{
|
|
if (!m_observerEnvironmentObjects.contains(id))
|
|
return;
|
|
|
|
if (!minefield->isValidObjectIdentifier() ||
|
|
!minefield->isValidMineType() ||
|
|
!minefield->isValidMineCount() ||
|
|
!minefield->isValidActivationTime() ||
|
|
!minefield->isValidAreaEffectSimulationName() ||
|
|
!minefield->isValidForceIdentifier() ||
|
|
!minefield->isValidPointsData())
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.MineField"))
|
|
<< "Wanted to create Minefield but not all necessary data is available yet. :(";
|
|
return;
|
|
}
|
|
|
|
if (minefield->isValidPercentComplete() && minefield->getPercentComplete() > 99)
|
|
return;
|
|
|
|
IdentifierStruct is(minefield->getObjectIdentifier());
|
|
|
|
AreaEffectSimulation::MineAreaModifyRequest ma;
|
|
|
|
const auto ct = m_ngsHandler->ppmHandler()->chargeTypeFromDisEntity(TypeStruct(minefield->getMineType()).toString());
|
|
|
|
ma.externalId(is.toInt64());
|
|
ma.chargeTypeId(ct.id());
|
|
ma.density(0.008 * minefield->getMineCount() + 0.1); // 0 -> 0.1 , 100 -> 0.9
|
|
ma.effectStart(getMSecsSinceEpoch(minefield->getActivationTime()));
|
|
ma.name(minefield->getAreaEffectSimulationName().str());
|
|
if (minefield->isValidDuration())
|
|
ma.effectDuration(60LL * 60 * 1000 * minefield->getDuration()); // Hours to MSecs
|
|
else
|
|
ma.effectDuration(60LL * 60 * 1000 * 4); // 4 Hour Default
|
|
int partyId = m_ngsHandler->ppmHandler()->partyIdFromForceIdentifier(minefield->getForceIdentifier());
|
|
ma.partyId(partyId);
|
|
double width;
|
|
std::vector<Core::GeoPosition2D> segments;
|
|
if (!getCorridorSegment(minefield->getPointsData(), segments, width))
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.MineField"))
|
|
<< "Minefield Id: " << is.toString()
|
|
<< ", Name: " << ma.name()
|
|
<< ". Could not calculate segment from given points data.";
|
|
return;
|
|
}
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.MineField"))
|
|
<< "Minefield added/changed: Id: " << is.toString()
|
|
<< ", Name: " << ma.name();
|
|
|
|
ma.segments(segments);
|
|
ma.width(width);
|
|
ma.isCenterLine(true);
|
|
|
|
emit newMinefield(ma);
|
|
m_nonpublishedEnvironmentObjects.remove(id);
|
|
|
|
});
|
|
return true;
|
|
*/
|
|
}
|
|
|
|
bool NgsConnector::addMinefieldBreach(const rpr2::IObserverGuezMineFieldBreachObjInstance *minefieldBreach)
|
|
{
|
|
return false;
|
|
/*
|
|
QTimer::singleShot(STATUS_WAIT_INTERVAL, this, [this, minefieldBreach]() mutable
|
|
{
|
|
if (!minefieldBreach->isValidObjectIdentifier() ||
|
|
!minefieldBreach->isValidActivationTime() ||
|
|
!minefieldBreach->isValidAreaEffectSimulationName() ||
|
|
!minefieldBreach->isValidForceIdentifier() ||
|
|
!minefieldBreach->isValidPointsData())
|
|
return;
|
|
|
|
IdentifierStruct is(minefieldBreach->getObjectIdentifier());
|
|
// If it was deleted, don't do anything!
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return;
|
|
|
|
AreaEffectSimulation::MineCorridorModifyRequest mc;
|
|
|
|
mc.externalId(is.toInt64());
|
|
mc.effectStart(getMSecsSinceEpoch(minefieldBreach->getActivationTime()));
|
|
mc.name(minefieldBreach->getAreaEffectSimulationName().str());
|
|
|
|
std::vector<Core::GeoPosition2D> vec;
|
|
double width;
|
|
|
|
if (!getCorridorSegment(minefieldBreach->getPointsData(), vec, width))
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.MineFieldBreach"))
|
|
<< "Minefield Breach Id: " << is.toString()
|
|
<< ", Name: " << mc.name()
|
|
<< ". Could not calculate segment from given points data.";
|
|
return;
|
|
}
|
|
mc.segments(vec);
|
|
mc.width(width);
|
|
int partyId = m_ngsHandler->ppmHandler()->partyIdFromForceIdentifier(minefieldBreach->getForceIdentifier());
|
|
mc.partyId(partyId);
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.MineFieldBreach"))
|
|
<< "Minefield added/changed: Id: " << is.toString()
|
|
<< ", Name: " << mc.name();
|
|
|
|
emit newMinefieldBreach(mc);
|
|
m_nonpublishedEnvironmentObjects.remove(is.entityNumber());
|
|
|
|
});
|
|
return true;
|
|
*/
|
|
}
|
|
|
|
bool NgsConnector::onSpatialChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::WorldLocationStruct &wl, qint64 simTimeMSecs)
|
|
{
|
|
return false;
|
|
/*
|
|
IdentifierStruct is(eis);
|
|
ParticipantPosition newParticipantPosition(wl);
|
|
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
ParticipantPosition &posInMapRef = m_observerPositions[is.entityNumber()];
|
|
if (!posInMapRef.hasMoved(newParticipantPosition)) //Hat sich die Position zum letzen Mal signifkant geändert?
|
|
return true;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.Position"))
|
|
<< "Player: " << is.toString() << ", Position: " << newParticipantPosition.toString() << ", Time: " << newParticipantPosition.msec;
|
|
|
|
posInMapRef = newParticipantPosition;
|
|
|
|
emit spatialChanged(is.entityNumber(), newParticipantPosition, simTimeMSecs);
|
|
|
|
return true;
|
|
*/
|
|
}
|
|
|
|
void NgsConnector::onEntityTypeChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::EntityTypeStruct &ets, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
TypeStruct ts(ets);
|
|
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << is.toString() << ". New Entity Type: " << ts.toString() << ". This has no effect!";
|
|
|
|
// Todo?
|
|
}
|
|
|
|
void NgsConnector::onIsPartOfChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::IsPartOfStruct &ipos, qint64 simTimeMSecs)
|
|
{
|
|
// We cannot handle Saab players being mounted on GUEZ vehicles and vice versa as on radio the HOST (party A) tells about its mounted players,
|
|
// whereas on HLA the player (party B) has to tell where he's mounted on. Party A's Excon cannot publish (IsPartOf) data of the player that
|
|
// belongs to party B.
|
|
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
|
|
int eqNo = is.entityNumber();
|
|
int eqNoHost = ipos.HostEntityIdentifier.EntityNumber;
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << is.toString() << " is now part of " << IdentifierStruct(ipos.HostEntityIdentifier).toString();
|
|
emit isPartOfChanged(eqNo, eqNoHost, simTimeMSecs);
|
|
}
|
|
|
|
bool NgsConnector::onMarkingChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::MarkingStruct &marking, qint64 simTimeMSecs)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
QByteArray ba;
|
|
for (size_t i = 0; i < marking.MarkingData.size(); ++i)
|
|
ba += marking.MarkingData[i];
|
|
const QString str(QString::fromUtf8(ba));
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has new Marking: '" << str << "'.";
|
|
|
|
emit markingChanged(eis.EntityNumber, str, simTimeMSecs);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::onPointsDataChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::ArrayOfWorldLocationStructDynamicHLAlengthlessVarArray &points, qint64 simTimeMSecs)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
std::vector<Core::GeoPosition2D> pointsData;
|
|
|
|
for (size_t i = 0; i < points.size(); ++i)
|
|
pointsData.resize(pointsData.size() + 1, ParticipantPosition(points[i]).toGeoPosition2D());
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has new Points data (not printed) of size " << pointsData.size();
|
|
|
|
emit aesPointsDataChanged(is.toInt64(), pointsData, simTimeMSecs);
|
|
|
|
return true;
|
|
}
|
|
bool NgsConnector::onForceIdentifierChanged(const rpr2::EntityIdentifierStruct &eis, rpr2::ForceIdentifierEnum8::ET identifier, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.Player"))
|
|
<< "Player: " << is.toString() << " has new Force Identifier: " << identifier << ". This has NO EFFECT.";
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::onForceIdentifierChangedEO(const rpr2::EntityIdentifierStruct &eis, rpr2::ForceIdentifierEnum8::ET identifier, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has new Force Identifier: " << identifier << ". Updating AES Item.";
|
|
|
|
int partyId = -1; // = m_ngsHandler->ppmHandler()->partyIdFromForceIdentifier(identifier);
|
|
|
|
emit aesForceIdentifierChanged(is.toInt64(), partyId);
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::onTacticalStatusChanged(const rpr2::EntityIdentifierStruct &eis,
|
|
const rpr2::TacticalStatusStruct &rprStatus,
|
|
qint64 simTimeMSecs)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
ensureDamageModelExists(is);
|
|
m_damageModelMap[is.entityNumber()]->setTacticalStatusStruct(rprStatus, simTimeMSecs);
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.Status"))
|
|
<< "Player: " << is.toString() << " New Total Status: " << rprStatus.TotalStatus << ", Tactical Status (unused): " << rprStatus.TacticalStatus;
|
|
|
|
if (rprStatus.TotalStatus == rpr2::TotalStatusEnum32::CombatReady)
|
|
{
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.Status")) << "New Status is CombarReady. Therfore we 'init' the player.";
|
|
emit participantReceivedInit(is.entityNumber(), simTimeMSecs);
|
|
return true;
|
|
}
|
|
// Todo: Tactical Status Change on SAAB players can occur at any time (without known reason). Therefore, we MUST handle this.
|
|
// Change of Tactical Status with no other Interaction cannot be handled (at the moment). The Interaction forwards the status change to PPM.
|
|
// Note: We could start a timer per eqNo. If the Timer is not deleted by an interaction that handles it, send it out.
|
|
|
|
GuezHitStruct hitStruct;
|
|
hitStruct.originatorChargeTypeEtsString = TypeStruct::fromDisInt(0).toString();
|
|
hitStruct.originatorId = 0;
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::Unknown;
|
|
hitStruct.position = m_observerPositions[is.entityNumber()].toGeoPosition();
|
|
hitStruct.sampleTime = simTimeMSecs;
|
|
hitStruct.targetId = is.entityNumber();
|
|
hitStruct.vulnerabilityState = ProjectDataManagement::VulnerabilityState_def::VulnerabilityBitsChanged; // --> Evaluate State from Bits (done in PPM Service).
|
|
hitStruct.vulnerabilityKind = 0;
|
|
|
|
const auto vulnerabilityBits = m_damageModelMap[is.entityNumber()]->totalState(hitStruct.sampleTime);
|
|
hitStruct.vulnerabilityBits = (vulnerabilityBits & ~rpr2::TotalStatusEnum32::Manipulation);
|
|
|
|
if (m_guezHitActive.contains(hitStruct.targetId))
|
|
{
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.StatusChange")) << "Tactical Status changed, but GuezHit was detected before. Not doing anything!";
|
|
return true;
|
|
}
|
|
|
|
QTimer::singleShot(Settings::guezHitGraceTimeMSecs(), this, [this, hitStruct]() mutable
|
|
{
|
|
if (m_guezHitActive.contains(hitStruct.targetId))
|
|
{
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Player.StatusChange")) << "Tactical Status changed, Timeout happened, but GuezHit was detected before. Not doing anything!";
|
|
return;
|
|
}
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.Player.StatusChange")) << "Tactical Status changed, Timeout happened. NO corresponding GuezHit detected";
|
|
emit guezHit(hitStruct);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
|
|
bool NgsConnector::onDeactivatedChanged(const rpr2::EntityIdentifierStruct &eis, bool state, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has changed 'Deactivated' State. New State: " << state;
|
|
|
|
if (state) // now deactivated
|
|
{
|
|
emit aesRemoveItem(is.toInt64());
|
|
|
|
// int activationTime = 0;
|
|
// const rpr2::IObserverGuezMineFieldObjInstance *minefield = dynamic_cast<const rpr2::IObserverGuezMineFieldObjInstance * >(m_observerEnvironmentObjects[is.entityNumber()]);
|
|
// if (minefield && minefield->isValidActivationTime())
|
|
// activationTime = getMSecsSinceEpoch(minefield->getActivationTime());
|
|
// const rpr2::IObserverGuezMineFieldBreachObjInstance *minefieldBreach = dynamic_cast<const rpr2::IObserverGuezMineFieldBreachObjInstance * >(m_observerEnvironmentObjects[is.entityNumber()]);
|
|
// if (minefieldBreach && minefieldBreach->isValidActivationTime())
|
|
// activationTime = getMSecsSinceEpoch(minefieldBreach->getActivationTime());
|
|
|
|
// // again!
|
|
// if (activationTime > 0)
|
|
// emit aesRemoveItem(is.toInt64());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NgsConnector::onPercentCompleteChanged(const rpr2::EntityIdentifierStruct &eis, ngs::UINT32 state, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return true;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has changed 'Percent Complete'. New Completeness: " << state;
|
|
|
|
// Find out, if it was active before
|
|
// Todo: This might not work as the instance's deactivated flag most likely already is set...
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return false;
|
|
|
|
if (state > 99)
|
|
emit aesRemoveItem(is.toInt64());
|
|
|
|
return true;
|
|
}
|
|
|
|
// Minefield
|
|
// Minefield Breach
|
|
void NgsConnector::onAreaEffectSimulationNameChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::OMT13string &value, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(eis.EntityNumber))
|
|
return;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has changed Name. New Name: " << QString::fromStdString(value);
|
|
|
|
emit aesNameChanged(is.toInt64(), value);
|
|
}
|
|
|
|
// Minefield
|
|
// Minefield Breach
|
|
void NgsConnector::onActivationTimeChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::ClockTimeStruct &value, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(eis.EntityNumber))
|
|
return;
|
|
|
|
qint64 msecs = getMSecsSinceEpoch(value);
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has changed Activation Time: " << msecs;
|
|
|
|
emit aesActivationTimeChanged(is.toInt64(), msecs);
|
|
}
|
|
|
|
// Minefield
|
|
void NgsConnector::onDurationChanged(const rpr2::EntityIdentifierStruct &eis, ngs::UINT32 value, qint64 simTimeMSecs)
|
|
{
|
|
Q_UNUSED(simTimeMSecs);
|
|
IdentifierStruct is(eis);
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
if (m_nonpublishedEnvironmentObjects.contains(is.entityNumber()))
|
|
return;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(eis.EntityNumber))
|
|
return;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
<< "Object: " << is.toString() << " has changed Duration: " << value;
|
|
|
|
emit aesDurationChanged(is.toInt64(), value);
|
|
}
|
|
|
|
// Minefield
|
|
void NgsConnector::onMineTypeChanged(const rpr2::EntityIdentifierStruct &eis, const rpr2::EntityTypeStruct &ets, qint64 simTimeMSecs)
|
|
{
|
|
IdentifierStruct is(eis);
|
|
Q_UNUSED(simTimeMSecs);
|
|
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
if (!m_observerEnvironmentObjects.contains(is.entityNumber()))
|
|
return;
|
|
|
|
if (m_observerEnvironmentObjects.contains(eis.EntityNumber))
|
|
return;
|
|
|
|
// const auto ct = m_ngsHandler->ppmHandler()->chargeTypeFromDisEntity(TypeStruct(ets).toString());
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Inbound.Object"))
|
|
// << "Object: " << is.toString() << " has changed Munition: " << ct.disEntity() << " / internal id: " << ct.id();
|
|
// emit aesChargeChanged(is.toInt64(), ct.id());
|
|
}
|
|
|
|
// HLA -> DDS
|
|
void NgsConnector::onNewMunitionDetonation(const rpr2::IObserverMunitionDetonationIntInstance &interaction)
|
|
{
|
|
// Own Item?
|
|
if (std::stol(interaction.getEventIdentifier().IssuingObjectIdentifier.ID) == IdentifierStruct(0).toInt64())
|
|
return;
|
|
|
|
// AreaEffectSimulation::ExplosionSingleModifyRequest req;
|
|
|
|
// // req.altitude();
|
|
// const auto ct = m_ngsHandler->ppmHandler()->chargeTypeFromDisEntity(TypeStruct(interaction.getMunitionType()).toString());
|
|
// req.chargeTypeId(ct.id());
|
|
// req.id(0);
|
|
// req.effectStart(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch() + ACTIVATION_LEAD_TIME);
|
|
// IdentifierStruct is(interaction.getEventIdentifier().EventCount);
|
|
// is.setSiteId(255); // Dummy - Must not be of either site.
|
|
// req.externalId(is.toInt64()); // dummy val, inserted to prevent aes_handler from dropping this telegram
|
|
// req.fireRequestTime(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch());
|
|
// req.impactPosition(ParticipantPosition(interaction.getDetonationLocation()).toGeoPosition2D());
|
|
// // IdentifierStruct is = IdentifierStruct::fromInt64(QString::fromStdString(interaction.getEventIdentifier().IssuingObjectIdentifier.ID).toLongLong());
|
|
// req.name(tr("SAAB Fire: %1").arg(interaction.getEventIdentifier().EventCount).toStdString());
|
|
// // Todo: If SAAB sends the Party in interaction.getFiringObjectIdentifier().ID like "F12" -> "ForceIdentifierEnum -> Value 12"
|
|
// // req.partyId(interaction.getFiringObjectIdentifier())
|
|
// // req.purpose()
|
|
// // req.rotation()
|
|
// DEBUG_LOG(getLogger("NgsConnector.Inbound.MunitionDetonation"))
|
|
// << "Munition Detonation: "
|
|
// << "Location: " << ParticipantPosition(interaction.getDetonationLocation()).toString()
|
|
// << ", Charge Type: " << ct.disEntity();
|
|
|
|
// emit munitionDetonation(req);
|
|
}
|
|
|
|
int NgsConnector::getEquipmentNoByRTIObjectId(const std::string &sender) const
|
|
{
|
|
// Own Players
|
|
for (auto it(m_playerMap.cbegin()); it != m_playerMap.cend(); ++it)
|
|
{
|
|
if (it.value()->isValidObjectName())
|
|
{
|
|
if (it.value()->getObjectName() == sender)
|
|
return it.key();
|
|
}
|
|
}
|
|
// Saab Players
|
|
for (auto it(m_observerPlayerInstances.cbegin()); it != m_observerPlayerInstances.cend(); ++it)
|
|
{
|
|
if (it.value()->isValidObjectName())
|
|
{
|
|
if (it.value()->getObjectName() == sender)
|
|
return it.key();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// HLA -> DDS
|
|
void NgsConnector::onNewWeaponFire(const rpr2::IObserverWeaponFireIntInstance &interaction)
|
|
{
|
|
// Self issued?
|
|
if (std::stol(interaction.getEventIdentifier().IssuingObjectIdentifier.ID) == IdentifierStruct(0).toInt64())
|
|
return;
|
|
|
|
// TrainingAreaBase::EquipmentGearEvent event;
|
|
// event.equipmentNumber(getEquipmentNoByRTIObjectId(interaction.getFiringObjectIdentifier().ID));
|
|
// // only send for others, not for own players
|
|
// if (m_playerMap.contains(event.equipmentNumber()))
|
|
// return;
|
|
|
|
// TrainingAreaBase::GearCharge charge;
|
|
// const auto ct = m_ngsHandler->ppmHandler()->chargeTypeFromDisEntity(TypeStruct(interaction.getMunitionType()).toString());
|
|
// charge.chargeTypeId(ct.id());
|
|
// // charge.gearId();
|
|
// // charge.gearTypeId();
|
|
// // charge.remain();
|
|
|
|
// event.charge(charge);
|
|
// event.chargeAmount(interaction.getQuantityFired());
|
|
// event.sampleTime(simTimeToMSec(interaction.getReceiveTimeStamp()));
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Inbound.WeaponFire"))
|
|
// << "Weapon Fire: EventID: " << interaction.getEventIdentifier().EventCount
|
|
// << ", Charge Type: " << ct.disEntity()
|
|
// << ", Shooter: " << event.equipmentNumber()
|
|
// << ", Rounds: " << interaction.getQuantityFired() << ")";
|
|
|
|
// emit weaponFire(event);
|
|
}
|
|
|
|
void NgsConnector::onNewGuezHit(const rpr2::IObserverGuezHitIntInstance &interaction)
|
|
{
|
|
IdentifierStruct is(interaction.getTargetIdentifier());
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
if (!m_observerPlayerInstances.contains(is.entityNumber()))
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.GuezHit"))
|
|
<< "Player: " << is.toString()
|
|
<< ", but there's no observer Object for it.";
|
|
return;
|
|
}
|
|
|
|
const int eqNo = interaction.getTargetIdentifier().EntityNumber;
|
|
auto ptr = m_damageModelMap.value(eqNo);
|
|
if (!ptr)
|
|
{
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.GuezHit"))
|
|
<< "Player: " << eqNo
|
|
<< ", Damage Model no longer exists. Not processing GuezHit!";
|
|
return;
|
|
}
|
|
ptr->setTacticalStatus(interaction.getHitResult(), simTimeToMSec(interaction.getReceiveTimeStamp()));
|
|
|
|
|
|
GuezHitStruct hitStruct;
|
|
hitStruct.originatorChargeTypeEtsString = TypeStruct(interaction.getMunition()).toString();
|
|
hitStruct.originatorId = interaction.getOriginatorIdentifier().EntityNumber;
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::Unknown;
|
|
switch (interaction.getOriginatorType())
|
|
{
|
|
case rpr2::OriginatorTypeEnum16::Unknown:
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::Unknown;
|
|
break;
|
|
case rpr2::OriginatorTypeEnum16::NoMedicalTreatment: // If no medical treatment has been conducted, and there's no originator, he's bleeding for himself...
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::Participant;
|
|
if (hitStruct.originatorId == 0) // for sanity, there can't be a participant with EqId = 0
|
|
hitStruct.originatorId = hitStruct.targetId;
|
|
break;
|
|
case rpr2::OriginatorTypeEnum16::Participant:
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::Participant;
|
|
if (hitStruct.originatorId == 0) // for sanity, there can't be a participant with EqId = 0
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::ExerciseControl;
|
|
break;
|
|
case rpr2::OriginatorTypeEnum16::AreaEffectSimulation:
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::AreaEffectSimulation;
|
|
hitStruct.originatorId = IdentifierStruct(interaction.getOriginatorIdentifier()).toInt64();
|
|
break;
|
|
case rpr2::OriginatorTypeEnum16::ObserverController:
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::ObserverController;
|
|
break;
|
|
case rpr2::OriginatorTypeEnum16::ExerciseControl:
|
|
hitStruct.originatorType = ProjectDataManagement::StateChangeOriginator_def::ExerciseControl;
|
|
break;
|
|
}
|
|
hitStruct.position = ParticipantPosition(interaction.getTargetLocation()).toGeoPosition();
|
|
hitStruct.sampleTime = simTimeToMSec(interaction.getReceiveTimeStamp());
|
|
hitStruct.targetId = interaction.getTargetIdentifier().EntityNumber;
|
|
// hitStruct.vulnerabilityState = ProjectDataManagement::VulnerabilityState_def::VulnerabilityBitsChanged; // --> Evaluate State from Bits (done in PPM Service).
|
|
// hitStruct.vulnerabilityKind = 0;
|
|
hitStruct.vulnerabilityState = getTacticalStatusEnum(interaction.getHitResult());
|
|
|
|
// HAck for resetting a player, whilst SAAB does not send the correct HitResult...
|
|
if ((hitStruct.originatorType == ProjectDataManagement::StateChangeOriginator_def::ExerciseControl ||
|
|
hitStruct.originatorType == ProjectDataManagement::StateChangeOriginator_def::ObserverController
|
|
)
|
|
&& hitStruct.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::HitWithNoEffect)
|
|
{
|
|
auto ptr = m_damageModelMap.value(eqNo);
|
|
if (ptr)
|
|
{
|
|
hitStruct.vulnerabilityState = ptr->vulnerabilityState(hitStruct.sampleTime);
|
|
if (hitStruct.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CombatReady)
|
|
ptr->setTacticalStatus(rpr2::HitResultEnum16::Reset, simTimeToMSec(interaction.getReceiveTimeStamp()));
|
|
}
|
|
}
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezHit"))
|
|
<< "Player: " << is.toString()
|
|
<< ", Originator Type: " << hitStruct.originatorType
|
|
<< ", Originator Id: " << hitStruct.originatorId
|
|
<< ", Charge Type: " << hitStruct.originatorChargeTypeEtsString
|
|
<< ", HitResult: " << hitStruct.vulnerabilityState;
|
|
|
|
m_guezHitActive.insert(hitStruct.targetId);
|
|
|
|
QTimer::singleShot(Settings::guezHitGraceTimeMSecs(), this, [this, hitStruct, eqNo]() mutable
|
|
{
|
|
auto ptr = m_damageModelMap.value(eqNo);
|
|
if (!ptr)
|
|
{
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.GuezHit"))
|
|
<< "Player: " << eqNo
|
|
<< ", Damage Model no longer exists. Not processing GuezHit!";
|
|
return;
|
|
}
|
|
const auto vulnerabilityBits = ptr->totalState(hitStruct.sampleTime);
|
|
hitStruct.vulnerabilityBits = (vulnerabilityBits & ~rpr2::TotalStatusEnum32::Manipulation);
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezHit")) << "vBits: " << vulnerabilityBits;
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezHit")) << "vState: " << hitStruct.vulnerabilityState;
|
|
m_guezHitActive.remove(hitStruct.targetId);
|
|
emit guezHit(hitStruct);
|
|
});
|
|
}
|
|
|
|
void NgsConnector::onNewGuezInit(const rpr2::IObserverGuezInitIntInstance &interaction)
|
|
{
|
|
// ExConEngagement FROM HLA TO US! Our Player shall be affected!
|
|
IdentifierStruct is(interaction.getEntityIdentifier());
|
|
if (!is.isOwnElement())
|
|
return;
|
|
|
|
if (!m_playerMap.contains(is.entityNumber()))
|
|
{
|
|
ERROR_LOG(getLogger("NgsConnector.Inbound.GuezInit"))
|
|
<< "Player: " << is.toString()
|
|
<< " is not our player...";
|
|
return;
|
|
}
|
|
rpr2::ResetPlayerEnum8::ET rp = interaction.getResetPlayer();
|
|
rpr2::ActivateHelmetObservationEnum8::ET aho = interaction.getActivateHelmetObservation();
|
|
bool resetVulnerabilityState = true;
|
|
if (rp != rpr2::ResetPlayerEnum8::CombatReadyWithoutReammunition &&
|
|
rp != rpr2::ResetPlayerEnum8::CombatReadyWithReammunition)
|
|
resetVulnerabilityState = false;
|
|
|
|
if (aho != rpr2::ActivateHelmetObservationEnum8::NoChange)
|
|
{
|
|
WARNING_LOG(getLogger("NgsConnector.Inbound.GuezInit"))
|
|
<< "Player: " << is.toString()
|
|
<< "Incoming Activation Helmet/Vest on GuezInit not supported yet";
|
|
}
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezInit"))
|
|
<< "Player: " << is.toString()
|
|
<< ", Reset Type: " << rp;
|
|
|
|
emit guezInit(is.entityNumber(), false, rp == rpr2::ResetPlayerEnum8::CombatReadyWithReammunition, resetVulnerabilityState);
|
|
|
|
}
|
|
|
|
void NgsConnector::onNewGuezBiteReport(const rpr2::IObserverGuezBiteReportIntInstance &interaction)
|
|
{
|
|
IdentifierStruct is(interaction.getEntityIdentifier());
|
|
if (is.isOwnElement())
|
|
return;
|
|
|
|
// TrainingAreaBase::EquipmentBite eb;
|
|
|
|
// QStringList result;
|
|
// bool leave = false;
|
|
// if (!interaction.isValidBiteResult())
|
|
// {
|
|
// result << QStringLiteral("BiteResult not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (!interaction.isValidConfigurationComparisonResult())
|
|
// {
|
|
// result << QStringLiteral("ConfigurationComparison not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (!interaction.isValidDiscoveredDevices())
|
|
// {
|
|
// result << QStringLiteral("DiscoveredDevices not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (!interaction.isValidEntityIdentifier())
|
|
// {
|
|
// result << QStringLiteral("EntityIdentifier not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (!interaction.isValidRegistrationType())
|
|
// {
|
|
// result << QStringLiteral("RegistrationType not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (!interaction.isValidReportTime())
|
|
// {
|
|
// result << QStringLiteral("ReportTime not valid");
|
|
// leave = true;
|
|
// }
|
|
// if (leave)
|
|
// {
|
|
// ERROR_LOG(getLogger("NgsConnector.Inbound.GuezBiteReport"))
|
|
// << "Player: " << is.toString()
|
|
// << ", Cannot process Interaction. Reason(s): " << result.join(QLatin1String(", "));
|
|
// return;
|
|
// }
|
|
|
|
// rpr2::BiteResultStruct brs = interaction.getBiteResult();
|
|
|
|
// eb.configState(brs.DeviceOkay);
|
|
// eb.batteryState(brs.BatteryWarning);
|
|
|
|
// std::vector<TrainingAreaBase::EquipmentBiteError> be;
|
|
// be.resize(brs.ErrorCodes.size());
|
|
// for (unsigned int i = 0; i < brs.ErrorCodes.size(); ++i)
|
|
// be[i].canDeviceNumber(brs.ErrorCodes[i].DeviceId);
|
|
|
|
// eb.biteErrors(be);
|
|
// eb.biteState(interaction.getDiscoveredDevices());
|
|
// eb.configError(interaction.getConfigurationComparisonResult());
|
|
// eb.equipmentNumber(is.entityNumber());
|
|
// eb.registerType(interaction.getRegistrationType());
|
|
// eb.sampleTime(getMSecsSinceEpoch(interaction.getReportTime()));
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezBiteReport"))
|
|
// << "Player: " << is.toString()
|
|
// << ", Device Okay: " << brs.DeviceOkay
|
|
// << ", Battery Warning: " << brs.BatteryWarning
|
|
// << ", Bite Error Count: " << be.size()
|
|
// << ", Registration Type: " << eb.registerType()
|
|
// << ", Config Error: " << eb.configError();
|
|
|
|
// emit biteReport(eb);
|
|
|
|
}
|
|
|
|
void NgsConnector::onNewGuezRequestBiteReport(const rpr2::IObserverGuezRequestBiteReportIntInstance &interaction)
|
|
{
|
|
IdentifierStruct is(interaction.getEntityIdentifier());
|
|
if (!is.isOwnElement())
|
|
return;
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Inbound.GuezBiteRequest"))
|
|
<< "Player: " << is.toString()
|
|
<< ", Bite Report Type: " << interaction.getBiteReportType();
|
|
|
|
// TrainingAreaBase::DemandBiteRequest dbr;
|
|
// dbr.equipmentNumbers().push_back(is.entityNumber());
|
|
// dbr.requestId(1);
|
|
// dbr.withSelfTest(interaction.getBiteReportType() == rpr2::BiteReportTypeEnum8::StatusAfterSelftest);
|
|
// emit biteRequest(dbr);
|
|
}
|
|
|
|
rpr2::EventIdentifierStruct NgsConnector::getEventIdentifierStruct()
|
|
{
|
|
rpr2::EventIdentifierStruct evis;
|
|
evis.EventCount = m_eventCount++ % std::numeric_limits<ngs::UINT16>::max();
|
|
evis.IssuingObjectIdentifier.ID = std::to_string(IdentifierStruct(0).toInt64());
|
|
if (m_eventCount > std::numeric_limits<ngs::UINT16>::max())
|
|
emit eventCountOverflow();
|
|
return evis;
|
|
}
|
|
|
|
rpr2::TacticalStatusStruct NgsConnector::getTacticalStatusFromState(const ParticipantManagement::StateInformation &state)
|
|
{
|
|
// rpr2::TacticalStatusStruct ts;
|
|
// ts.TacticalStatus = static_cast<rpr2::TacticalStatusEnum8::ET>(state.vulnerabilityState().underlying());
|
|
// ts.TotalStatus = static_cast<rpr2::TotalStatusEnum32::ET>(state.vulnerabilityBits());
|
|
// ts.VulnerabilityKind = state.vulnerabilityKindId();
|
|
// return ts;
|
|
}
|
|
|
|
bool NgsConnector::setVulnerabilityState(int eqNo, const ParticipantManagement::StateInformation &state)
|
|
{
|
|
return false;
|
|
/*
|
|
rpr2::TacticalStatusStruct ts = getTacticalStatusFromState(state);
|
|
rpr2::IPlayerPhysicalEntityObjInstance *playerInstance = dynamic_cast<rpr2::IPlayerPhysicalEntityObjInstance *>(m_playerMap.value(eqNo, nullptr));
|
|
if (!playerInstance)
|
|
return false;
|
|
|
|
DamageModel dm(ts);
|
|
playerInstance->setDamageState(dm.damageState(-1));
|
|
playerInstance->setImmobilized(dm.immobilized(-1));
|
|
playerInstance->setFirePowerDisabled(dm.firePowerDisabled(-1));
|
|
|
|
DEBUG_LOG(getLogger("NgsConnector.Outbound.Player.Status"))
|
|
<< "Player: " << eqNo
|
|
<< ", New Total Status: " << ts.TotalStatus
|
|
<< ", New Tactical Status (shall be unused): " << ts.TacticalStatus;
|
|
|
|
rpr2::IPlayerGuezHumanObjInstance *humanInstance = dynamic_cast<rpr2::IPlayerGuezHumanObjInstance *>(playerInstance);
|
|
if (humanInstance)
|
|
{
|
|
humanInstance->setTacticalStatus(ts);
|
|
playerInstance->publish(getSimTime(state.stateTime()));
|
|
return true;
|
|
}
|
|
|
|
rpr2::IPlayerGuezGroundVehicleObjInstance *groundVehicleInstance = dynamic_cast<rpr2::IPlayerGuezGroundVehicleObjInstance *>(playerInstance);
|
|
if (groundVehicleInstance)
|
|
{
|
|
groundVehicleInstance->setTacticalStatus(ts);
|
|
playerInstance->publish(getSimTime(state.stateTime()));
|
|
return true;
|
|
}
|
|
|
|
ERROR_LOG(getLogger("NgsConnector.Outbound.Player.Status"))
|
|
<< "Player: " << eqNo
|
|
<< " is not Human or GroundVehicle. Cannot set status.";
|
|
return false;
|
|
*/
|
|
}
|
|
|
|
// Hit from Participant Management
|
|
//bool NgsConnector::setParticipantHit(int eqNo, const ParticipantManagement::StateInformation &state,
|
|
// const ParticipantPosition &partPos, int chargeType,
|
|
// ProjectDataManagement::StateChangeOriginator originatorType, int originatorEqNo)
|
|
//{
|
|
// // Set Tactical Status on Player
|
|
// auto *playerInstanceDest = m_playerMap.value(eqNo, nullptr);
|
|
// if (!playerInstanceDest || !playerInstanceDest->isValidEntityIdentifier())
|
|
// return false;
|
|
|
|
// if (!setVulnerabilityState(eqNo, state))
|
|
// return false;
|
|
|
|
// // Put Munition Detonation on HLA
|
|
// rpr2::IPlayerGuezHitIntClass &ic = m_somPlayer->getPlayerGuezHitIntClass();
|
|
// rpr2::IPlayerGuezHitIntInstance &icb = ic.newGuezHitIntInstance();
|
|
|
|
// icb.setMunition(getEtsCharge(chargeType));
|
|
// icb.setTargetIdentifier(playerInstanceDest->getEntityIdentifier());
|
|
// icb.setTargetLocation(partPos.toWorldLocation());
|
|
// icb.setHitResult(getHitResultEnum(state.vulnerabilityState()));
|
|
// IdentifierStruct is(0); // own excon
|
|
|
|
// rpr2::OriginatorTypeEnum16::ET originatorTypeRpr = rpr2::OriginatorTypeEnum16::Unknown;
|
|
|
|
// switch (originatorType.underlying())
|
|
// {
|
|
// case ProjectDataManagement::StateChangeOriginator_def::AreaEffectSimulation:
|
|
// {
|
|
// if (m_environmentObjects.contains(originatorEqNo)) // It's our AesItem, originatorEqNo is AesItemId is Entity Number
|
|
// is = IdentifierStruct(10 * originatorEqNo);
|
|
// else
|
|
// {
|
|
// // Obtain ExternalId
|
|
// int64_t externalId = m_ngsHandler->aesHandler()->externalId(originatorEqNo);
|
|
|
|
// // At this map, Entities and Objects are
|
|
// if (m_observerPlayerInstances.contains(externalId))
|
|
// {
|
|
// const rpr2::IObserverBaseEntityObjInstance *instance = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance * >(m_observerPlayerInstances[originatorEqNo]);
|
|
// if (instance->isValidEntityIdentifier())
|
|
// is = IdentifierStruct(instance->getEntityIdentifier());
|
|
// }
|
|
// }
|
|
// originatorTypeRpr = rpr2::OriginatorTypeEnum16::AreaEffectSimulation;
|
|
// break;
|
|
// }
|
|
// case ProjectDataManagement::StateChangeOriginator_def::ExerciseControl:
|
|
// originatorTypeRpr = rpr2::OriginatorTypeEnum16::ExerciseControl;
|
|
// break;
|
|
// case ProjectDataManagement::StateChangeOriginator_def::ObserverController:
|
|
// originatorTypeRpr = rpr2::OriginatorTypeEnum16::ObserverController;
|
|
// break;
|
|
// case ProjectDataManagement::StateChangeOriginator_def::Participant:
|
|
// if (originatorType == ProjectDataManagement::StateChangeOriginator_def::Participant)
|
|
// {
|
|
// if (m_playerMap.contains(originatorEqNo))
|
|
// is = IdentifierStruct(originatorEqNo);
|
|
// else if (m_observerPlayerInstances.contains(originatorEqNo))
|
|
// {
|
|
// // Works as long as externalID == equipmentNo
|
|
// const rpr2::IObserverBaseEntityObjInstance *instance = dynamic_cast<const rpr2::IObserverBaseEntityObjInstance * >(m_observerPlayerInstances[originatorEqNo]);
|
|
// if (instance->isValidEntityIdentifier())
|
|
// is = IdentifierStruct(instance->getEntityIdentifier());
|
|
// }
|
|
// originatorTypeRpr = rpr2::OriginatorTypeEnum16::Participant;
|
|
// break;
|
|
// }
|
|
// Q_FALLTHROUGH();
|
|
// case ProjectDataManagement::StateChangeOriginator_def::Initialization:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::FunctionalArea:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::MaintainanceDevice:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::Unknown:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::WoundTreatmentDevice:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::MedicalTimeout:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::Sanitation:
|
|
// // Todo: Check, if IED and DUSMine actually can be handled correctly:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::ImprovisedExplosiveDevice:
|
|
// case ProjectDataManagement::StateChangeOriginator_def::DusMine:
|
|
// originatorTypeRpr = rpr2::OriginatorTypeEnum16::Unknown;
|
|
// break;
|
|
// }
|
|
// icb.setOriginatorIdentifier(is.toEIS());
|
|
// icb.setOriginatorType(originatorTypeRpr);
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Outbound.GuezHit"))
|
|
// << "Player: " << eqNo
|
|
// << ", Originator Type: " << originatorType
|
|
// << ", Originator EIS: " << is.toString()
|
|
// << ", Charge Type: " << TypeStruct(getEtsCharge(chargeType)).toString()
|
|
// << ", Vulnerability State: " << state.vulnerabilityState();
|
|
|
|
// try
|
|
// {
|
|
// icb.publish(getSimTime(state.stateTime()));
|
|
// }
|
|
// catch (...)
|
|
// {
|
|
// ERROR_LOG(getLogger("NgsConnector.Outbound.GuezHit"))
|
|
// << "Player: " << eqNo
|
|
// << ", could not publish GuezHit!";
|
|
// }
|
|
|
|
// return true;
|
|
//}
|
|
|
|
//bool NgsConnector::setWeaponFire(int eqNo, const ParticipantManagement::ParticipantGearEvent &data)
|
|
//{
|
|
// rpr2::IPlayerWeaponFireIntClass &ic = m_somPlayer->getPlayerWeaponFireIntClass();
|
|
// rpr2::IPlayerWeaponFireIntInstance &icb = ic.newWeaponFireIntInstance();
|
|
|
|
// // FiringInstance ermitteln
|
|
// rpr2::RTIObjectIdStruct rSource;
|
|
// rSource.ID = std::to_string(IdentifierStruct(0).toInt64()); // Own Excon
|
|
// if (eqNo > 0)
|
|
// {
|
|
// auto *playerInstanceSource = m_playerMap.value(eqNo);
|
|
// if (!playerInstanceSource || !playerInstanceSource->isValidObjectName() || !playerInstanceSource->isValidSpatial())
|
|
// return false;
|
|
// rSource.ID = playerInstanceSource->getObjectName();
|
|
// icb.setFiringLocation(playerInstanceSource->getSpatial().DeadReckoningAlgorithm__A__Alternatives.SpatialStatic().WorldLocation);
|
|
// }
|
|
|
|
// icb.setEventIdentifier(getEventIdentifierStruct());
|
|
//// icb.setFireControlSolutionRange();
|
|
//// icb.setFireMissionIndex();
|
|
// icb.setFiringObjectIdentifier(rSource);
|
|
// icb.setFuseType(rpr2::FuseTypeEnum16::Other);
|
|
// icb.setInitialVelocityVector(rpr2::VelocityVectorStruct());
|
|
//// icb.setMunitionObjectIdentifier();
|
|
// icb.setMunitionType(getEtsCharge(data.charge().chargeTypeId()));
|
|
// icb.setQuantityFired(data.chargeAmount());
|
|
//// icb.setRateOfFire();
|
|
//// icb.setTargetObjectIdentifier();
|
|
// icb.setWarheadType(rpr2::WarheadTypeEnum16::Kinetic);
|
|
|
|
// icb.publish(getSimTime(data.sampleTime()));
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Outbound.WeaponFire"))
|
|
// << "Weapon Fire: "
|
|
// << "Charge Type: " << data.charge().chargeTypeId()
|
|
// << ", Shooter: " << eqNo
|
|
// << ", Rounds: " << data.chargeAmount();
|
|
|
|
// return true;
|
|
//}
|
|
|
|
//bool NgsConnector::setEquipmentBite(int eqNo, const TrainingAreaBase::EquipmentBite &data)
|
|
//{
|
|
// IdentifierStruct is = getIdentifierStructbyEquipmentNo(eqNo);
|
|
|
|
// if (is.isNull() || !is.isOwnElement())
|
|
// return false;
|
|
|
|
// rpr2::IPlayerGuezBiteReportIntClass &icx = m_somPlayer->getPlayerGuezBiteReportIntClass();
|
|
// rpr2::IPlayerGuezBiteReportIntInstance *icb = &icx.newGuezBiteReportIntInstance();
|
|
// rpr2::BiteResultStruct brs;
|
|
|
|
// brs.BatteryWarning = static_cast<rpr2::BatteryWarningEnum32::ET>(data.batteryState());
|
|
// brs.DeviceOkay = static_cast<rpr2::CanDeviceEnum32::ET>(data.configState());
|
|
// rpr2::ErrorStructVariableArray errorCodes;
|
|
// errorCodes.resize(data.biteErrors().size());
|
|
// int i = 0;
|
|
// for (const auto &error : data.biteErrors())
|
|
// {
|
|
// errorCodes[i].DeviceId = error.canDeviceNumber();
|
|
// errorCodes[i].SubDeviceId = error.subdeviceNumber();
|
|
// errorCodes[i].UniqueSubdeviceId = error.uniqueId();
|
|
// errorCodes[i].ErrorId = error.errorNumber();
|
|
// ++i;
|
|
// }
|
|
// brs.ErrorCodes = errorCodes;
|
|
// icb->setBiteResult(brs);
|
|
// icb->setConfigurationComparisonResult(data.configError());
|
|
// icb->setDiscoveredDevices(static_cast<rpr2::CanDeviceEnum32::ET>(data.biteState()));
|
|
// icb->setEntityIdentifier(is.toEIS());
|
|
// icb->setRegistrationType(static_cast<rpr2::RegistrationTypeEnum8::ET>(data.registerType()));
|
|
// icb->setReportTime(getClockTimeStruct(data.sampleTime()));
|
|
// icb->publish(getSimTime(data.sampleTime()));
|
|
|
|
// DEBUG_LOG(getLogger("NgsConnector.Outbound.GuezBiteReport"))
|
|
// << "Player: " << is.toString()
|
|
// << ", Device Okay: " << brs.DeviceOkay
|
|
// << ", Battery Warning: " << brs.BatteryWarning
|
|
// << ", Bite Error Count: " << errorCodes.size()
|
|
// << ", Registration Type: " << data.registerType()
|
|
// << ", Config Error: " << data.configError();
|
|
|
|
// return true;
|
|
//}
|
|
|
|
} // namespace HighLevelArchitecture
|