Пример #1
0
////////////////////////////////////////////////////////
// TEST: testSendTSOInteractionWithInvalidParameter() //
////////////////////////////////////////////////////////
void SendInteractionTest::testSendTSOInteractionWithInvalidParameter()
{
	RTI::ParameterHandleValuePairSet *params = defaultFederate->createPHVPS( 2 );
	params->add( xaHandle, "xa", 3 );
	params->add( 10000000, "no", 3 );
	
	try
	{
		RTIfedTime theTime = 10.0;
		defaultFederate->rtiamb->sendInteraction( yHandle, *params, theTime, "NA" );
		delete params;
		failTestMissingException( "InteractionParameterNotDefined", 
		                          "sending interaction with invalid param handle" );
	}
	catch( RTI::InteractionParameterNotDefined &ipnd )
	{
		// success!
		delete params;
	}
	catch( RTI::Exception &e )
	{
		delete params;
		failTestWrongException( "InteractionParameterNotDefined", e,
		                        "sending interaction with invalid param handle" );
	}
}
Пример #2
0
/*
 * This method will send out an interaction of the type InteractionRoot.X. Any
 * federates which are subscribed to it will receive a notification the next time
 * they tick(). Here we are passing only two of the three parameters we could be
 * passing, but we don't actually have to pass any at all!
 */
void ExampleCPPFederate::sendInteraction()
{
	///////////////////////////////////////////////
	// create the necessary container and values //
	///////////////////////////////////////////////
	// create the collection to store the values in
	RTI::ParameterHandleValuePairSet *parameters = RTI::ParameterSetFactory::create( 2 );

	// generate the new values
	char xaValue[16], xbValue[16];
	sprintf( xaValue, "xa:%f", getLbts() );
	sprintf( xbValue, "xb:%f", getLbts() );
	parameters->add( xaHandle, xaValue, (RTI::ULong)strlen(xaValue)+1 );
	parameters->add( xbHandle, xbValue, (RTI::ULong)strlen(xbValue)+1 );

	//////////////////////////
	// send the interaction //
	//////////////////////////
	rtiamb->sendInteraction( xHandle, *parameters, "hi!" );

	// if you want to associate a particular timestamp with the
	// interaction, you will have to supply it to the RTI. Here
	// we send another interaction, this time with a timestamp:
	RTIfedTime time = fedamb->federateTime + fedamb->federateLookahead;
	rtiamb->sendInteraction( xHandle, *parameters, time, "hi!" );

	// clean up
	delete parameters;
}
Пример #3
0
void
Master_FA::receiveInteraction (
	RTI::InteractionClassHandle theInteraction,
	const RTI::ParameterHandleValuePairSet & theParameters,
	const RTI::FedTime & theTime,
	const char * theTag,
	RTI::EventRetractionHandle theHandle)
	throw (
		RTI::InteractionClassNotKnown,
		RTI::InteractionParameterNotKnown,
		RTI::InvalidFederationTime,
		RTI::FederateInternalError)
	{
	RTIfedTime fed_time(theTime);
	cout << "Incoming interaction at time " << fed_time.getTime() << endl;
	if (theInteraction != reply_handle)
		{
		cerr << "Received unknown interaction " << theInteraction << endl;
		return;
		}
	if (theParameters.size() != 3)
		{
		cerr << "Unexpected number of parameters " 
			 << theParameters.size() << endl;
		return;
		}

	// extract values
	RTI::ULong	id;
	RTI::Double	change_lat;
	RTI::Double	change_long;
	unsigned long length;
	RTI::ParameterHandle handle;
    char buffer [20];

	for (unsigned long i = 0; i < 3; i++)
		{
		handle = theParameters.getHandle (i);
		if (handle == reply_parameters [Id])
			{
			theParameters.getValue (i, buffer, length);
			Sim_Hla_Istream is (buffer, length);
			is >> id;
			}
		else if (handle == reply_parameters [ChangeLat])
Пример #4
0
//-----------------------------------------------------------------
//
// METHOD:
//     void Country::Update( RTI::InteractionClassHandle theInteraction,
//                    const RTI::ParameterHandleValuePairSet& theParameters )
//
// PURPOSE:
//     Process an interaction.
//
// RETURN VALUES:
//     None. 
//
// HISTORY:
//     1) Created 11/6/96
//     2) Updated to RTI 1.3 3/26/98
//
//-----------------------------------------------------------------
void Country::Update( RTI::InteractionClassHandle theInteraction,
             const RTI::ParameterHandleValuePairSet& theParameters )
{
   if ( theInteraction == Country::GetCommRtiId() )
   {
      RTI::ParameterHandle paramHandle;
      RTI::ULong           valueLength;

      // We need to iterate through the AttributeHandleValuePairSet
      // to extract each AttributeHandleValuePair.  Based on the type
      // specified ( the value returned by getHandle() ) we need to
      // extract the data frlom the buffer that is returned by 
      // getValue().
      for ( unsigned int i = 0; i < theParameters.size(); i++ )
      {
         paramHandle = theParameters.getHandle( i );
         if ( paramHandle == Country::GetMessageRtiId() )
         {
            // When we run this over multiple platforms we will have
            // a problem with different endian-ness of platforms. Either
            // we need to encode the data using something like XDR or
            // provide another mechanism.
            char msg[ 1024 ];
            theParameters.getValue( i, (char*)msg, valueLength );
            cout << "FED_HW: Interaction Received: " << msg << endl;
         }
         else
         {
            // There must be an error since there should only be
            // one parameter to Communication.
            cerr << "FED_HW: Error: I seem to have received a parameter for "
                 << "interaction class Communication that I don't "
                 << "know about." << endl;
         }
      }
   }
   else
   {
      cerr << "FED_HW: Recieved an interaction class I don't know about." << endl;   
   }
}
//------------------------------------------------------------------------------
// munitionDetonationMsgFactory() -- (Output) Munition detonation message factory
//------------------------------------------------------------------------------
bool Nib::munitionDetonationMsgFactory(const double)
{
   std::cout << "rprfom::Nib::sendMunitionDetonation() HERE!!" << std::endl;

   // Early out -- we must be registered
   if (!isRegistered()) return false;

   NetIO* netIO = static_cast<NetIO*>(getNetIO());

   // Create the parameter/value set
   RTI::ParameterHandleValuePairSet* pParams =
      RTI::ParameterSetFactory::create( NetIO::NUM_INTERACTION_PARAMETER );

   // Set our mode so that we don't do this again.
   setMode(simulation::Player::DETONATED);

   // If our player just detonated, then it must be a weapon!
   simulation::Weapon* mPlayer = dynamic_cast<simulation::Weapon*>(getPlayer());
   if (mPlayer == nullptr) return false;   // Early out -- it wasn't a weapon

   // ---
   // Event ID
   // ---
   unsigned short fireEvent = getWeaponFireEvent();
   EventIdentifierStruct eventIdentifier;
   base::NetHandler::toNetOrder(&eventIdentifier.eventCount, fireEvent);
   base::utStrncpy(
      reinterpret_cast<char*>(&eventIdentifier.issuingObjectIdentifier.id[0]),
      sizeof(eventIdentifier.issuingObjectIdentifier.id),
      getObjectName(),
      RTIObjectIdStruct::ID_SIZE );    
   pParams->add(
      netIO->getInteractionParameterHandle(NetIO::EVENT_IDENTIFIER_MD_PI),
      reinterpret_cast<char*>(&eventIdentifier),
      sizeof(EventIdentifierStruct) );

   // ---
   // Location & Velocity
   // ---
   {
      osg::Vec3d geocPos = getDrPosition();
      osg::Vec3d geocVel = getDrVelocity();
      osg::Vec3d geocAcc = getDrAcceleration();

      // World Coordinates
      WorldLocationStruct detonationLocation;
      base::NetHandler::toNetOrder(&detonationLocation.x, geocPos[base::Nav::IX]);
      base::NetHandler::toNetOrder(&detonationLocation.y, geocPos[base::Nav::IY]);
      base::NetHandler::toNetOrder(&detonationLocation.z, geocPos[base::Nav::IZ]);
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::DETONATION_LOCATION_MD_PI), 
         reinterpret_cast<char*>(&detonationLocation), 
         sizeof(WorldLocationStruct) );

      // Velocity
      VelocityVectorStruct finalVelocityVector; 
      base::NetHandler::toNetOrder(&finalVelocityVector.xVelocity, static_cast<float>(geocVel[base::Nav::IX]));
      base::NetHandler::toNetOrder(&finalVelocityVector.yVelocity, static_cast<float>(geocVel[base::Nav::IY]));
      base::NetHandler::toNetOrder(&finalVelocityVector.zVelocity, static_cast<float>(geocVel[base::Nav::IZ]));
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::FINAL_VELOCITY_VECTOR_MD_PI), 
         reinterpret_cast<char*>(&finalVelocityVector), 
         sizeof(VelocityVectorStruct) );
   }

   // ---
   // Munition Object identifiers:
   // ---
   {
      RTIObjectIdStruct munitionObjectIdentifier;
      base::utStrncpy(
         reinterpret_cast<char*>(&munitionObjectIdentifier.id[0]),
         sizeof(munitionObjectIdentifier.id),
         getObjectName(),
         RTIObjectIdStruct::ID_SIZE );    
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::MUNITION_OBJECT_IDENTIFIER_MD_PI),
         reinterpret_cast<char*>(&munitionObjectIdentifier),
         sizeof(RTIObjectIdStruct) );
   }

   // ---
   // Firing Object identifier:
   //
   // Get the firing player and its NIB.
   //   First check to see if it's an IPlayer from an HLA network.
   //   If it's not, then check our output list.
   // ---
   {
      Nib* fNib = nullptr;
      simulation::Player* fPlayer = mPlayer->getLaunchVehicle();
      if (fPlayer != nullptr) {
         if (fPlayer->isNetworkedPlayer()) {
            fNib = dynamic_cast<Nib*>( fPlayer->getNib() );
         }
         else {
            fNib = dynamic_cast<Nib*>( netIO->findNib(fPlayer, simulation::NetIO::OUTPUT_NIB) );
         }
      }

      if (fNib != nullptr) {
         RTIObjectIdStruct firingObjectIdentifier;
         base::utStrncpy(
            reinterpret_cast<char*>(&firingObjectIdentifier.id[0]),
            sizeof(firingObjectIdentifier.id),
            fNib->getObjectName(),
            RTIObjectIdStruct::ID_SIZE );    
         pParams->add(
            netIO->getInteractionParameterHandle(NetIO::FIRING_OBJECT_IDENTIFIER_MD_PI),
            reinterpret_cast<char*>(&firingObjectIdentifier),
            sizeof(RTIObjectIdStruct) );
      }
   }

   // ---
   // Target Object identifier:
   //
   // Get the target player and its NIB.
   //   First check to see if it's an IPlayer from an HLA network.
   //   If it's not, then check our output list.
   // ---
   {
      Nib* tNib = nullptr;
      simulation::Player* tPlayer = mPlayer->getTargetPlayer();
      if (tPlayer != nullptr) {
         tNib = dynamic_cast<Nib*>( tPlayer->getNib() );
         if (tNib == nullptr)
            tNib = dynamic_cast<Nib*>( netIO->findNib(tPlayer, simulation::NetIO::OUTPUT_NIB) );
      }

      if (tNib != nullptr) {
         RTIObjectIdStruct targetObjectIdentifier;
         base::utStrncpy(
            reinterpret_cast<char*>(&targetObjectIdentifier.id[0]),
            sizeof(targetObjectIdentifier.id),
            tNib->getObjectName(),
            RTIObjectIdStruct::ID_SIZE );    
         pParams->add(
            netIO->getInteractionParameterHandle(NetIO::TARGET_OBJECT_IDENTIFIER_MD_PI),
            reinterpret_cast<char*>(&targetObjectIdentifier),
            sizeof(RTIObjectIdStruct) );
      }
   }

   // ---
   // Munition Type
   // ---
   {
      EntityTypeStruct munitionType;
      munitionType.entityKind = getEntityKind();
      munitionType.domain = getEntityDomain();
      base::NetHandler::toNetOrder(&munitionType.countryCode, getEntityCountry() );
      munitionType.category  = getEntityCategory();
      munitionType.subcategory = getEntitySubcategory();
      munitionType.specific   = getEntitySpecific();
      munitionType.extra  = getEntityExtra();
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::MUNITION_TYPE_MD_PI),
         reinterpret_cast<char*>(&munitionType),
         sizeof(EntityTypeStruct) );
   }

   // ---
   // Fuse Type (16 bit enum)
   // ---
   {
      FuseTypeEnum16 fuseType = FuseTypeOther;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, static_cast<unsigned short>(fuseType) );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::FUSE_TYPE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Quantity fired
   // ---
   {
      unsigned short quantityFired = 1;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, quantityFired );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::QUANTITY_FIRED_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Rate Of Fire
   // ---
   {
      unsigned short rateOfFire = 0;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, rateOfFire );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::RATE_OF_FIRE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Warhead type
   // ---
   {
      WarheadTypeEnum16 warheadType = WarheadTypeOther;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, static_cast<unsigned short>(warheadType) );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::WARHEAD_TYPE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Relative detonation location
   // ---
   {
      RelativePositionStruct relativeDetonationLocation;
      relativeDetonationLocation.bodyXDistance = 0;
      relativeDetonationLocation.bodyYDistance = 0;
      relativeDetonationLocation.bodyZDistance = 0;

      RelativePositionStruct netBuffer;
      base::NetHandler::toNetOrder(&netBuffer.bodyXDistance, relativeDetonationLocation.bodyXDistance );
      base::NetHandler::toNetOrder(&netBuffer.bodyYDistance, relativeDetonationLocation.bodyYDistance );
      base::NetHandler::toNetOrder(&netBuffer.bodyZDistance, relativeDetonationLocation.bodyZDistance );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::RELATIVE_DETONATION_LOCATION_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(RelativePositionStruct) );
   }

   // ---
   // Detonation result code
   // ---
   {
      DetonationResultCodeEnum8 detonationResultCode;
      switch ( mPlayer->getDetonationResults() ) {
         case simulation::Weapon::DETONATE_OTHER :
            detonationResultCode = DetonationResultCodeOther;
            break;
         case simulation::Weapon::DETONATE_ENTITY_IMPACT :
            detonationResultCode = EntityImpact;
            break;
         case simulation::Weapon::DETONATE_ENTITY_PROXIMATE_DETONATION :
            detonationResultCode = EntityProximateDetonation;
            break;
         case simulation::Weapon::DETONATE_GROUND_IMPACT :
            detonationResultCode = GroundImpact;
            break;
         case simulation::Weapon::DETONATE_GROUND_PROXIMATE_DETONATION :
            detonationResultCode = GroundProximateDetonation;
            break;
         case simulation::Weapon::DETONATE_DETONATION :
            detonationResultCode = Detonation;
            break;
         case simulation::Weapon::DETONATE_NONE :
            detonationResultCode = None;
            break;
         default :
            detonationResultCode = DetonationResultCodeOther;
            break;
      };

      unsigned char netBuffer = static_cast<unsigned char>(detonationResultCode);
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::DETONATION_RESULT_CODE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned char) );
   }

   // ---
   // Send the interaction
   // ---
   bool ok = netIO->sendInteraction(
      netIO->getInteractionClassHandle(NetIO::MUNITION_DETONATION_INTERACTION), pParams );

   // don't need this anymore
   delete pParams;

   return ok;
}
Пример #6
0
//-----------------------------------------------------------------
//
// METHOD:
//     void Country::Update( RTIfedTime& newTime )
//
// PURPOSE:
//     Update the state of the Country's population based on
//     the new time value.  The deltaTime is calculated based
//     on the last time the Country object was updated and
//     the newTime passed in.  The deltaTime is multiplied by
//     the growth rate and current population to determine the
//     number of births in the deltaTime.  The population is
//     increased by the number of births.
//
// RETURN VALUES:
//     None. 
//
// HISTORY:
//     1) Created 11/6/96
//     2) Updated to RTI 1.3 3/26/98
//
//-----------------------------------------------------------------
void Country::Update( RTI::FedTime& newTime )
{
   //------------------------------------------------------
   // we have advanced in time so calculate my next state.
   //------------------------------------------------------

   RTI::FedTime *pTime = RTI::FedTimeFactory::makeZero();
   (*pTime) = newTime;
   (*pTime) -= this->GetLastTime();
   // Set last time to new time
   this->SetLastTime( newTime );

   if ( !(pTime->isZero()))
   {
      SetPopulation( GetPopulation() + 
                     (GetPopulation()*ms_growthRate) );
   }

   if ( ms_rtiAmb )
   {
      //------------------------------------------------------
      // Update state of country
      //------------------------------------------------------
      try
      {
         //------------------------------------------------------
         // In order to send the values of our attributes, we must
         // construct an AttributeHandleValuePairSet (AHVPS) which
         // is a set comprised of attribute handles, values, and
         // the size of the values. CreateNVPSet() is a method 
         // defined on the Country class - it is not part of the RTI.
         // Look inside the method to see how to construct an AHVPS
         //------------------------------------------------------
         RTI::AttributeHandleValuePairSet* pNvpSet = this->CreateNVPSet();
         
         //------------------------------------------------------
         // Send the AHVPS to the federation.
         //
         // this call returns an event retraction handle but we 
         // don't support event retraction so no need to store it.
         //------------------------------------------------------
         (void) ms_rtiAmb->updateAttributeValues( this->GetInstanceId(),
                                                  *pNvpSet,
                                                  this->GetLastTimePlusLookahead(), 
                                                  NULL );
         // Must free the memory
         pNvpSet->empty();
         delete pNvpSet;
      }
      catch ( RTI::Exception& e )
      {
         cerr << "FED_HW: Error:" << e << endl;
      }
      
      // Periodically send an interaction to tell everyone Hello
      static int periodicMessage = 0;

      if ( (periodicMessage++%100) == 0 )
      {
         RTI::ParameterHandleValuePairSet* pParams = NULL;

                 //------------------------------------------------------
                 // Periodically stimulate an update of the "Name" 
                 // attribute for the benefit of late-arriving federates.
                 // It would be more correct to use 
                 // "requestClassAttributeValueUpdate" and 
                 // "provideAttributeValueUpdate", but let's keep things
                 // simple.
                 //------------------------------------------------------
         hasNameChanged = RTI::RTI_TRUE;

         //------------------------------------------------------
         // Set up the data structure required to push this
         // objects's state to the RTI.  The
         // ParameterHandleValuePairSet is similar to the AHVPS
         // except it contains ParameterHandles instead of
         // AttributeHandles.
         //------------------------------------------------------
         pParams = RTI::ParameterSetFactory::create( 1 );

         char *pMessage = "Hello World!";
         
         pParams->add( this->GetMessageRtiId(),
                       (char*) pMessage,
                       ((strlen(pMessage)+1)*sizeof(char)) );
         try
         {
            //------------------------------------------------------
            // this call returns an event retraction handle but we 
            // don't support event retraction so no need to store it.
            //------------------------------------------------------
            (void) ms_rtiAmb->sendInteraction( GetCommRtiId(), *pParams,
                                               this->GetLastTimePlusLookahead(),
                                               NULL );
         }
         catch ( RTI::Exception& e )
         {
            cerr << "FED_HW: Error:" << e << endl;
         }

         //------------------------------------------------------
         // Must free the memory:
         //    ParameterSetFactory::create() allocates memory on
         //    the heap.
         //------------------------------------------------------
         delete pParams;
      }
   }
   delete pTime;
}
Пример #7
0
bool
HlaFedAmb::ReadDataIxnParameters(
    const RTI::ParameterHandleValuePairSet& theParameters,
    HlaDataIxnInfo& dataIxnInfo)
{
    HlaVariableDatumSetInfo& vdsInfo = dataIxnInfo.variableDatumSetInfo;

    unsigned i;
    for (i = 0; i < theParameters.size(); i++)
    {
        RTI::ParameterHandle ph = theParameters.getHandle(i);
        RTI::ULong size = theParameters.getValueLength(i);

        if (ph == m_dataOriginatingEntityHandle)
        {
            // Not used.
        }
        else
        if (ph == m_dataReceivingEntityHandle)
        {
            // Not used.
        }
        else
        if (ph == m_dataRequestIdentifierHandle)
        {
            // Not used.
        }
        else
        if (ph == m_dataFixedDatumsHandle)
        {
            // Not used.
        }
        else
        if (ph == m_dataVariableDatumSetHandle)
        {
            if (size > g_hlaVariableDatumSetBufSize)
            {
                if (m_debug)
                {
                    cout << "FED: Ignoring Data interaction containing"
                            " large VariableDatumSet parameter" << endl;
                }

                return false;
            }

            char variableDatumSet[g_hlaVariableDatumSetBufSize];
            theParameters.getValue(i, variableDatumSet, size);

            // NumberOfVariableDatums, DatumID, DatumLength.
            // Converted to host-byte-order.

            unsigned vdsOffset = 0;

            HlaCopyFromOffsetAndNtoh(
                &vdsInfo.numberOfVariableDatums,
                variableDatumSet,
                vdsOffset,
                sizeof(vdsInfo.numberOfVariableDatums));

            if (vdsInfo.numberOfVariableDatums != 1)
            {
                if (m_debug)
                {
                    cout << "FED: Ignoring Data interaction where"
                            " NumberOfVariableDatums != 1" << endl;
                }

                return false;
            }

            HlaVariableDatumInfo& vdInfo = vdsInfo.variableDatumsInfo[0];

            HlaCopyFromOffsetAndNtoh(
                &vdInfo.datumId,
                variableDatumSet,
                vdsOffset,
                sizeof(vdInfo.datumId));

            HlaCopyFromOffsetAndNtoh(
                &vdInfo.datumLength,
                variableDatumSet,
                vdsOffset,
                sizeof(vdInfo.datumLength));

            if (vdInfo.datumLength % 8 != 0)
            {
                if (m_debug)
                {
                    cout << "FED: Ignoring Data interaction where"
                            " DatumLength is not a multiple of 8" << endl;
                }

                return false;
            }

            unsigned datumLengthInBytes = vdInfo.datumLength / 8;

            if (datumLengthInBytes > g_hlaDatumValueBufSize)
            {
                if (m_debug)
                {
                    cout << "FED: Ignoring Data interaction containing"
                            " large DatumValue field" << endl;
                }

                return false;
            }

            // DatumValue.
            // Left in network-byte-order.

            HlaCopyFromOffset(
                vdInfo.datumValue,
                variableDatumSet,
                vdsOffset,
                datumLengthInBytes);
        }
        else
        {
            HlaReportError("Unknown parameter handle", __FILE__, __LINE__);
        }
    }//for//

    return true;
}
Пример #8
0
//------------------------------------------------------------------------------
// receiveMunitionDetonation() -- (Input) handles the Munition Detonation interaction
//------------------------------------------------------------------------------
bool NetIO::receiveMunitionDetonation(const RTI::ParameterHandleValuePairSet& theParameters)
{
    // Things we need
    RTIObjectIdStruct firingObjectIdentifier;
    RTIObjectIdStruct munitionObjectIdentifier;
    RTIObjectIdStruct targetObjectIdentifier;
    simulation::Weapon::Detonation detonationResult = simulation::Weapon::DETONATE_NONE;

    // ---
    // Extract the required data from the interaction's parameters
    // ---
    RTI::ULong length;
    char netBuffer[1000];
    for (RTI::ULong i = 0 ; i < theParameters.size(); i++ ) {
        
        // get the parameter's handed and data (network byte order)
        RTI::ParameterHandle theHandle = theParameters.getHandle(i);
        theParameters.getValue(i, netBuffer, length);

        // Process the parameter
        switch ( findParameterIndex(theHandle) ) {

        case DETONATION_RESULT_CODE_MD_PI : {

            switch ( DetonationResultCodeEnum8( netBuffer[0] ) ) {
                case DetonationResultCodeOther :
                    detonationResult = simulation::Weapon::DETONATE_OTHER;
                    break;
                case EntityImpact :
                    detonationResult = simulation::Weapon::DETONATE_ENTITY_IMPACT;
                    break;
                case EntityProximateDetonation :
                    detonationResult = simulation::Weapon::DETONATE_ENTITY_PROXIMATE_DETONATION;
                    break;
                case GroundImpact :
                    detonationResult = simulation::Weapon::DETONATE_GROUND_IMPACT;
                    break;
                case GroundProximateDetonation :
                    detonationResult = simulation::Weapon::DETONATE_GROUND_PROXIMATE_DETONATION;
                    break;
                case Detonation :
                    detonationResult = simulation::Weapon::DETONATE_DETONATION;
                    break;
                case None :
                    detonationResult = simulation::Weapon::DETONATE_NONE;
                    break;
                default :
                    detonationResult = simulation::Weapon::DETONATE_OTHER;
                    break;
            };
        }
        break;
        
        case FIRING_OBJECT_IDENTIFIER_MD_PI : {
            // Get the object's name
            RTI::ULong n = RTIObjectIdStruct::ID_SIZE;
            if (n > length) n = length;
            base::utStrncpy(reinterpret_cast<char*>(&firingObjectIdentifier.id[0]), sizeof(firingObjectIdentifier.id), netBuffer, n);
            firingObjectIdentifier.id[n-1] = '\0';   
        }
        break;
        
        case MUNITION_OBJECT_IDENTIFIER_MD_PI : {
            // Get the object's name
            RTI::ULong n = RTIObjectIdStruct::ID_SIZE;
            if (n > length) n = length;
            base::utStrncpy(reinterpret_cast<char*>(&munitionObjectIdentifier.id[0]), sizeof(munitionObjectIdentifier.id), netBuffer, n);
            munitionObjectIdentifier.id[n-1] = '\0';   
        }
        break;
        
        case TARGET_OBJECT_IDENTIFIER_MD_PI : {
            // Get the object's name
            RTI::ULong n = RTIObjectIdStruct::ID_SIZE;
            if (n > length) n = length;
            base::utStrncpy(reinterpret_cast<char*>(&targetObjectIdentifier.id[0]), sizeof(targetObjectIdentifier.id), netBuffer, n);
            targetObjectIdentifier.id[n-1] = '\0';   
        }
        break;
                        
        }
    }
    std::cout << "RprFom::Nib::receiveMunitionDetonation() fired(" << firingObjectIdentifier.id << ")"  << std::endl;
  
    // ---
    // 1) Find the target (local) player
    // ---
    simulation::Player* tPlayer = nullptr;
    if ( std::strlen(reinterpret_cast<const char*>(targetObjectIdentifier.id)) > 0 ) {
        simulation::Nib* tNib = findNibByObjectName( reinterpret_cast<char*>(targetObjectIdentifier.id), OUTPUT_NIB);
        if (tNib != nullptr) tPlayer = tNib->getPlayer();
    }
    
    // ---
    // Note: we're only interested (at this time) with our local players being hit
    // by other networked IPlayers.
    // ---
    if (tPlayer != nullptr) {
        
        // ---
        // 2) Find the firing player and munitions (networked) IPlayers
        // ---
        simulation::Nib* fNib = nullptr;
        simulation::Nib* mNib = nullptr;
        if ( std::strlen(reinterpret_cast<const char*>(firingObjectIdentifier.id)) > 0 ) {
            fNib = findNibByObjectName( reinterpret_cast<char*>(firingObjectIdentifier.id), INPUT_NIB);
        }
        if ( std::strlen(reinterpret_cast<const char*>(munitionObjectIdentifier.id)) > 0 ) {
            mNib = findNibByObjectName( reinterpret_cast<char*>(munitionObjectIdentifier.id), INPUT_NIB);
        }

        // ---
        // 3) Tell the target player that it was killed by the firing player
        // ---
        if (detonationResult == simulation::Weapon::DETONATE_ENTITY_IMPACT) {
            if (fNib != nullptr) {
                tPlayer->event(KILL_EVENT,fNib->getPlayer());
            }
            else {
                tPlayer->event(KILL_EVENT,0);   // killed by we don't know by whom
            }
        }
        
        // ---
        // 4) Update the mode of the munition IPlayer
        // ---
        if (mNib != nullptr) {
            simulation::Weapon* mPlayer = dynamic_cast<simulation::Weapon*>(mNib->getPlayer());
            if (mPlayer != nullptr) {
                mPlayer->setMode(simulation::Player::DETONATED);
                mPlayer->setDetonationResults(detonationResult);
            }
            mNib->setMode(simulation::Player::DETONATED);
        }
    }

    return true;
}