bool C4Network2IO::Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword) // by main thread { // get network class C4NetIO *pNetIO = getNetIO(eProt); if (!pNetIO) return false; // already connected/connecting? if (GetConnectionByConnAddr(addr, pNetIO)) return true; // assign new connection ID, peer address isn't known yet uint32_t iConnID = iNextConnID++; C4NetIO::addr_t paddr; ZeroMem(&paddr, sizeof paddr); // create connection object and add to list C4Network2IOConnection *pConn = new C4Network2IOConnection(); pConn->Set(pNetIO, eProt, paddr, addr, CS_Connect, szPassword, iConnID); pConn->SetCCore(nCCore); AddConnection(pConn); // connect if (!pConn->Connect()) { // show error LogF("Network: could not connect to %s:%d using %s: %s", inet_ntoa(addr.sin_addr), htons(addr.sin_port), getNetIOName(pNetIO), pNetIO->GetError() ? pNetIO->GetError() : ""); pNetIO->ResetError(); // remove class RemoveConnection(pConn); return false; } // ok, wait for connection return true; }
//------------------------------------------------------------------------------ // entityStateManager() -- (Output support) // -- Update the entity object for this NIB(Player) //------------------------------------------------------------------------------ bool Nib::entityStateManager(const double curExecTime) { bool ok = true; if (getPlayer()->isMode(simulation::Player::ACTIVE) && isPlayerStateUpdateRequired(curExecTime)) { // Need to update this entity object ... NetIO* netIO = static_cast<NetIO*>(getNetIO()); RTI::RTIambassador* rtiAmb = netIO->getRTIambassador(); // --- // First, make sure this entity has been registered // --- if (!isRegistered()) { try { RTI::ObjectClassHandle theClassHandle = netIO->getObjectClassHandle( getClassIndex() ); makeObjectName(); setObjectHandle( rtiAmb->registerObjectInstance( theClassHandle, getObjectName() ) ); netIO->addNibToObjectTables(this, simulation::NetIO::OUTPUT_NIB); std::cout << "rprfom::Nib::updateEntity(): Register entity: " << getObjectName() << " handle = " << getObjectHandle() << std::endl; } catch (RTI::Exception& e) { std::cerr << &e << std::endl; ok = false; } } // --- // Next, update the entity's attribute values ... // --- if ( ok && isRegistered()) { try { // Create the attribute-value pair set RTI::AttributeHandleValuePairSet* attrs = nullptr; attrs = RTI::AttributeSetFactory::create( NetIO::NUM_OBJECT_ATTRIBUTES ); // Load the set with updated attribute values updateBasicEntity(attrs,curExecTime); updatePhysicalEntity(attrs,curExecTime); updatePlatform(attrs,curExecTime); // Send attributes to the RTI //std::cout << "RprFom::Nib::updateEntity(): Update entity: " << getObjectName() << " handle = " << getObjectHandle() << std::endl; ok = netIO->updateAttributeValues(getObjectHandle(), attrs); delete attrs; } catch (RTI::Exception& e) { std::cerr << &e << std::endl; ok = false; } } } // end -- if active player needs an update return ok; }
void Ambassador::receiveInteraction ( RTI::InteractionClassHandle theInteraction, const RTI::ParameterHandleValuePairSet& theParameters, const char*) throw ( RTI::InteractionClassNotKnown, RTI::InteractionParameterNotKnown, RTI::FederateInternalError) { std::cout << "Ambassador::receiveInteraction(): " << theInteraction << std::endl; NetIO* netIO = getNetIO(); int idx = netIO->findInteractionClassIndex(theInteraction); if (idx != 0 && netIO->isInteractionClassSubscribed(idx)) { // It's an interaction that we subscribe to, so ... // just act as an interface to NetIO, which will handle this. getNetIO()->receiveInteraction(theInteraction, theParameters); } }
void Ambassador::discoverObjectInstance ( RTI::ObjectHandle theObject, RTI::ObjectClassHandle theObjectClass, const char * theObjectName) throw ( RTI::CouldNotDiscover, RTI::ObjectClassNotKnown, RTI::FederateInternalError) { std::cout << "Ambassador::discoverObjectInstance(): " << theObjectName << ", handle = " << theObject << std::endl; NetIO* netIO = getNetIO(); int classIndex = netIO->findObjectClassIndex(theObjectClass); if (classIndex != 0 && netIO->isObjectClassSubscribed(classIndex)) { // It's an object class that we've subscribed to ... // just act as an interface to NetIO, which will handle this. getNetIO()->discoverObjectInstance(theObject, theObjectClass, theObjectName); } }
//------------------------------------------------------------------------------ // setOutputPlayerType() -- sets the kind, country, ... variables //------------------------------------------------------------------------------ bool Nib::setOutputPlayerType(const models::Player* const p) { bool ok = false; if (getNetIO() != nullptr) { // Mark that we've been here. setEntityTypeChecked( true ); // Find "by player" on the output list const Ntm* typeMapper = getNetIO()->findNetworkTypeMapper(p); // If we found a type mapper for this Player type, // then set the mapper and copy the unique type codes if (typeMapper != nullptr) { ok = typeMapper->copyEntityType(this); if (ok) setTypeMapper(typeMapper); } } return ok; }
void Ambassador::turnInteractionsOff ( RTI::InteractionClassHandle theInteraction) throw ( RTI::InteractionClassNotPublished, RTI::FederateInternalError) { std::cout << "Ambassador::turnInteractionsOff(): " ; NetIO* netIO = getNetIO(); int idx = netIO->findInteractionClassIndex(theInteraction); if (idx != 0) { std::cout << idx; netIO->setInteractionEnabledFlag(idx,false); } std::cout << std::endl; }
void Ambassador::stopRegistrationForObjectClass ( RTI::ObjectClassHandle theClass) throw ( RTI::ObjectClassNotPublished, RTI::FederateInternalError) { //std::cout << "Ambassador::stopRegistrationForObjectClass(): "; NetIO* netIO = getNetIO(); int classIndex = netIO->findObjectClassIndex(theClass); if (classIndex != 0 ) { //std::cout << classIndex; netIO->setObjectClassRegistrationFlag(classIndex,false); } //std::cout << std::endl; }
void Ambassador::reflectAttributeValues ( RTI::ObjectHandle theObject, const RTI::AttributeHandleValuePairSet& theAttrs, const char* theTag) throw ( RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateOwnsAttributes, RTI::FederateInternalError) { //std::cout << "Ambassador::reflectAttributeValues(): object = " << theObject << ", theTag=" << theTag << std::endl; // find the input object NetIO* netIO = getNetIO(); Nib* nib = static_cast<Nib*>( netIO->findNibByObjectHandle(theObject, NetIO::INPUT_NIB) ); if (nib != nullptr) nib->reflectAttributeValues(theAttrs); }
//------------------------------------------------------------------------------ // turnUpdatesOffForObjectInstance //------------------------------------------------------------------------------ void Ambassador::turnUpdatesOffForObjectInstance ( RTI::ObjectHandle theObject, const RTI::AttributeHandleSet& theAttributes) throw ( RTI::ObjectNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) { //std::cout << "Ambassador:turnUpdatesOffForObjectInstance(): "; // Find the output object NetIO* netIO = getNetIO(); Nib* nib = static_cast<Nib*>(netIO->findNibByObjectHandle(theObject, NetIO::OUTPUT_NIB)); if (nib != 0) nib->turnUpdatesOff(theAttributes); //std::cout << std::endl; }
void Ambassador::startRegistrationForObjectClass ( RTI::ObjectClassHandle theClass) throw ( RTI::ObjectClassNotPublished, RTI::FederateInternalError) { //std::cout << "Ambassador::startRegistrationForObjectClass(): " ; NetIO* netIO = getNetIO(); int classIndex = netIO->findObjectClassIndex(theClass); if (classIndex != 0 && netIO->isObjectClassPublished(classIndex)) { // It's an object class that we publish, so we can start to // register our objects ... //std::cout << classIndex; netIO->setObjectClassRegistrationFlag(classIndex,true); } //std::cout << std::endl; }
void Ambassador::provideAttributeValueUpdate ( RTI::ObjectHandle theObject, const RTI::AttributeHandleSet& theAttrs) throw ( RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) { //std::cout << "Ambassador:provideAttributeValueUpdate(): "; // Find the output object NetIO* netIO = getNetIO(); Nib* nib = static_cast<Nib*>( netIO->findNibByObjectHandle(theObject, NetIO::OUTPUT_NIB) ); if (nib != nullptr) nib->provideAttributeValueUpdate(theAttrs); //std::cout << std::endl; }
void Ambassador::turnInteractionsOn ( RTI::InteractionClassHandle theInteraction) throw ( RTI::InteractionClassNotPublished, RTI::FederateInternalError) { std::cout << "Ambassador::turnInteractionsOn(): " ; NetIO* netIO = getNetIO(); int idx = netIO->findInteractionClassIndex(theInteraction); if (idx != 0 && netIO->isInteractionClassPublished(idx)) { // It's an interaction that we publish, so we can start // send new interactions of this class ... std::cout << idx; netIO->setInteractionEnabledFlag(idx,true); } std::cout << std::endl; }
void Ambassador::removeObjectInstance ( RTI::ObjectHandle theObject, const char* theTag) throw ( RTI::ObjectNotKnown, RTI::FederateInternalError) { std::cout << "Ambassador::removeObjectInstance(): remove object = " << theObject << ", theTag=" << theTag << std::endl; // find the input object NetIO* netIO = getNetIO(); Nib* nib = netIO->findNibByObjectHandle(theObject, NetIO::INPUT_NIB); if (nib != nullptr) { // set NIB delete request (Simulation::NetIO::cleanupInputList() should handle this) nib->setMode(simulation::Player::DELETE_REQUEST); } }
//------------------------------------------------------------------------------ // updatePhysicalEntity() -- (Output support) // -- sets the PhysicalEntity attribute values that need to be updated // // -- We send all published PhysicalEntity attributes every time. // The function isPlayerStateUpdateRequired() check if the player's state // needs to be re-sent. Therefore, we're not checking the individual update // required flags with isAttributeUpdateRequired(), but we do clear them // with setAttributeUpdateRequiredFlag(). // // (Also handles the host to network byte swapping) //------------------------------------------------------------------------------ void Nib::updatePhysicalEntity( RTI::AttributeHandleValuePairSet* attrs, const double) { // PhysicalEntity?? PhysicalEntity* physicalEntity = dynamic_cast<PhysicalEntity*>(baseEntity); if (physicalEntity != nullptr) { // Our handler NetIO* netIO = static_cast<NetIO*>(getNetIO()); // Force Identifier if (isAttributeUpdateEnabled(NetIO::FORCE_IDENTIFIER_AI)) { // Force ID: When mapping Player side to force IDs ... if (getSide() == simulation::Player::BLUE) { // blue's are friendly, ... physicalEntity->forceIdentifier = FRIENDLY; } else if (getSide() == simulation::Player::RED) { // red's are not, ... physicalEntity->forceIdentifier = OPPOSING; } else if (getSide() == simulation::Player::WHITE) { // white is neutral, ... physicalEntity->forceIdentifier = NEUTRAL; } else { // and everyone else is type OTHER. physicalEntity->forceIdentifier = OTHER; } //std::cout << "Send force: " << physicalEntity->forceIdentifier << std::endl;; unsigned char netBuffer = static_cast<unsigned char>(physicalEntity->forceIdentifier); // 8 bits enum type (ForceIdentifierEnum8) attrs->add(netIO->getObjectAttributeHandle( NetIO::FORCE_IDENTIFIER_AI), reinterpret_cast<char*>(&netBuffer), sizeof(netBuffer) ); setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, false); } } }
//------------------------------------------------------------------------------ // emitterBeamsManager() // -- (Output) Manages the emitter beam for this NIB(Player) //------------------------------------------------------------------------------ bool Nib::emitterBeamsManager(const LCreal curExecTime) { // --- // First, find all of our player's RfSensor systems and setup their handlers // --- if ( numEmissionSystems == 0 ) { // Check for the single-beam RADAR { // (DPG -- #### only a simple, single-beam Radar) const Basic::Pair * pair = getPlayer()->getSensorByType(typeid(Simulation::Radar)); if (pair != nullptr) { Simulation::RfSensor* rs = (Simulation::RfSensor*) pair->object(); // When we have a R/F sensor, create a handler for it EmissionPduHandler* handler = nullptr; // First, try to find an Emission PDU handler for this type system. // If we find one, then clone it for our use. NetIO* const disIO = static_cast<NetIO*>(getNetIO()); const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(rs); if (tmp != nullptr) { handler = tmp->clone(); } // Handler wasn't found? Then just create a simple, default emission handler if (handler == nullptr) { handler = new EmissionPduHandler(); } handler->setSensor( rs ); handler->setEmitterIdNumber( numEmissionSystems + 1 ); emitterSysHandler[numEmissionSystems] = handler; numEmissionSystems++; } } // end radar check // Check for a Jammer { const Basic::Pair * pair = getPlayer()->getSensorByType(typeid(Simulation::Jammer)); if (pair != nullptr) { Simulation::RfSensor* js = (Simulation::RfSensor*) pair->object(); bool singleBeam = true; Basic::PairStream* subcomponents = js->getComponents(); if (subcomponents != nullptr) { // Check for multi-beam jammer (each beam is a subcomponent Jammer) Basic::List::Item* item = subcomponents->getFirstItem(); while (item != nullptr && numEmissionSystems < MAX_EM_SYSTEMS) { Basic::Pair* pair = static_cast<Basic::Pair*>( item->getValue() ); Simulation::Jammer* jam = dynamic_cast<Simulation::Jammer*>( pair->object() ); if (jam != nullptr) { singleBeam = false; // When we have a R/F sensor, create a handler for it EmissionPduHandler* handler = nullptr; // First, try to find an Emission PDU handler for this type system. // If we find one, then clone it for our use. NetIO* const disIO = static_cast<NetIO*>(getNetIO()); const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(jam); if (tmp != nullptr) { handler = tmp->clone(); } // Handler wasn't found? Then just create a simple, default handler if (handler == nullptr) { handler = new EmissionPduHandler(); handler->setEmitterFunction(EmissionPduHandler::ESF_JAMMING); } handler->setSensor( jam ); handler->setEmitterIdNumber( numEmissionSystems + 1 ); emitterSysHandler[numEmissionSystems] = handler; numEmissionSystems++; } item = item->getNext(); } subcomponents->unref(); subcomponents = nullptr; } // Single beam jammer if (singleBeam && numEmissionSystems < MAX_EM_SYSTEMS) { // When we have a R/F sensor, create a handler for it EmissionPduHandler* handler = nullptr; // First, try to find an Emission PDU handler for this type system. // If we find one, then clone it for our use. NetIO* const disIO = static_cast<NetIO*>(getNetIO()); const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(js); if (tmp != nullptr) { handler = tmp->clone(); } // Handler wasn't found? Then just create a simple, default jammer handler if (handler == nullptr) { handler = new EmissionPduHandler(); handler->setEmitterFunction(EmissionPduHandler::ESF_JAMMING); } handler->setSensor( js ); handler->setEmitterIdNumber( numEmissionSystems + 1 ); emitterSysHandler[numEmissionSystems] = handler; numEmissionSystems++; } } } // end jammer check } // end (numEmissionSystems == 0) // --- // Have the handlers check their electromagnetic emission systems // and generate the PDUs as needed. // --- for (emissionSystemsIndex = 0; emissionSystemsIndex < numEmissionSystems; emissionSystemsIndex++) { if (emitterSysHandler[emissionSystemsIndex] != nullptr) { emitterSysHandler[emissionSystemsIndex]->updateOutgoing(curExecTime, this); } } return true; }
//------------------------------------------------------------------------------ // (Input) processElectromagneticEmissionPDU() //------------------------------------------------------------------------------ bool Nib::processElectromagneticEmissionPDU(const ElectromagneticEmissionPDU* const pdu) { bool ok = false; // --- // Loop through the Emission Systems in the PDU // --- for (unsigned char is = 0; is < pdu->numberOfSystems && is < MAX_EM_SYSTEMS; is++) { const EmissionSystem* es = pdu->getEmissionSystem(is); if (es != nullptr) { unsigned char idNum = es->emitterSystem.emitterIdentificationNumber; EmissionPduHandler* handler = nullptr; // --- // Does a handler for this system already exist in our list? // --- for (unsigned char i = 0; i < numEmissionSystems && handler == nullptr; i++) { if (idNum == emitterSysHandler[i]->getEmitterIdNumber()) { // Yes it does! handler = emitterSysHandler[i]; } } // --- // Create a handler if one doesn't already exist // --- if (handler == nullptr && numEmissionSystems < MAX_EM_SYSTEMS) { // First, try to find an Emission PDU handler for this type system. // If we find one, then clone it for our use. NetIO* const disIO = static_cast<NetIO*>(getNetIO()); const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(es); if (tmp != nullptr) { handler = tmp->clone(); } if (handler != nullptr) { // Handler found! handler->setEmitterIdNumber( idNum ); handler->setEmitterFunction( es->emitterSystem.function ); emitterSysHandler[numEmissionSystems] = handler; numEmissionSystems++; } else { // Handler wasn't found? std::cerr << "Dis::Nib::processElectromagneticEmissionPDU() warning: "; std::cerr << "EmissionPduHandler not found for emitterName: " << es->emitterSystem.emitterName; std::cerr << std::endl; } } // --- // Ok, pass the location of the EmissionSystem (and beam data) to the handler // --- if (handler != nullptr) { ok = handler->updateIncoming(pdu, es, this); } } } // End: for all systems return ok; }
//------------------------------------------------------------------------------ // reflectAttributeValues() -- (Input support) // Called by our FederateAmbassador to update the attribute values for // this object instance. (Also handles the network to host byte swapping) //------------------------------------------------------------------------------ void Nib::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& theAttrs) { NetIO* netIO = static_cast<NetIO*>(getNetIO()); if (netIO != nullptr && baseEntity != nullptr) { // PhysicalEntity pointer PhysicalEntity* physicalEntity = dynamic_cast<PhysicalEntity*>(baseEntity); RTI::ULong length; char netBuffer[1000]; for (RTI::ULong j = 0; j < theAttrs.size(); j++ ) { // get the attribute's handle and data (network byte order) RTI::AttributeHandle theAttr = theAttrs.getHandle(j); theAttrs.getValue(j, netBuffer, length); // Process the attribute switch ( netIO->findAttributeIndex(theAttr) ) { // Update Federate ID case NetIO::ENTITY_IDENTIFIER_AI : { EntityIdentifierStruct* net = reinterpret_cast<EntityIdentifierStruct*>(&netBuffer); base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.federateIdentifier.applicationID, net->federateIdentifier.applicationID ); base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.federateIdentifier.siteID, net->federateIdentifier.siteID ); base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.entityNumber, net->entityNumber ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, true); } break; // Update Entity Type case NetIO::ENTITY_TYPE_AI : { EntityTypeStruct* net = reinterpret_cast<EntityTypeStruct*>(&netBuffer); // All bytes except for country baseEntity->entityType = *net; base::NetHandler::fromNetOrder(&baseEntity->entityType.countryCode, net->countryCode ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, true); } break; // Update Spatial case NetIO::SPATIAL_AI : { // NIB's base entity structure pointers SpatialStruct* spatial = &(baseEntity->spatial); SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw); WorldLocationStruct* worldLocation = &spatialRvw->worldLocation; OrientationStruct* orientation = &spatialRvw->orientation; VelocityVectorStruct* velocityVector = &spatialRvw->velocityVector; AccelerationVectorStruct* accelerationVector = &spatialRvw->accelerationVector; AngularVelocityVectorStruct* angularVelocity = &spatialRvw->angularVelocity; // Net buffer component pointers SpatialStruct* netSpatial = reinterpret_cast<SpatialStruct*>(&netBuffer[0]); WorldLocationStruct* netWorldLocation = nullptr; OrientationStruct* netOrientation = nullptr; VelocityVectorStruct* netVelocityVector = nullptr; AccelerationVectorStruct* netAccelerationVector = nullptr; AngularVelocityVectorStruct* netAngularVelocity = nullptr; // Dead reckoning spatial->deadReckoningAlgorithm = netSpatial->deadReckoningAlgorithm; // find network components based on dead reckoning algorithm // (and set the isFrozen flag) switch (spatial->deadReckoningAlgorithm) { case DRM_STATIC : { SpatialStaticStruct* netSpatialStatic = reinterpret_cast<SpatialStaticStruct*>(&netBuffer[sizeof(SpatialStruct)]); spatialRvw->isFrozen = netSpatialStatic->isFrozen; netWorldLocation = &netSpatialStatic->worldLocation; netOrientation = &netSpatialStatic->orientation; } break; case DRM_FPW : { SpatialFPStruct* netSpatialFpw = reinterpret_cast<SpatialFPStruct*>(&netBuffer[sizeof(SpatialStruct)]); spatialRvw->isFrozen = netSpatialFpw->isFrozen; netWorldLocation = &netSpatialFpw->worldLocation; netOrientation = &netSpatialFpw->orientation; netVelocityVector = &netSpatialFpw->velocityVector; } break; case DRM_RPW : { SpatialRPStruct* netSpatialRpw = reinterpret_cast<SpatialRPStruct*>(&netBuffer[sizeof(SpatialStruct)]); spatialRvw->isFrozen = netSpatialRpw->isFrozen; netWorldLocation = &netSpatialRpw->worldLocation; netOrientation = &netSpatialRpw->orientation; netVelocityVector = &netSpatialRpw->velocityVector; netAngularVelocity = &netSpatialRpw->angularVelocity; } break; case DRM_RVW : { SpatialRVStruct* netSpatialRvw = reinterpret_cast<SpatialRVStruct*>(&netBuffer[sizeof(SpatialStruct)]); spatialRvw->isFrozen = netSpatialRvw->isFrozen; netWorldLocation = &netSpatialRvw->worldLocation; netOrientation = &netSpatialRvw->orientation; netVelocityVector = &netSpatialRvw->velocityVector; netAccelerationVector = &netSpatialRvw->accelerationVector; netAngularVelocity = &netSpatialRvw->angularVelocity; } break; case DRM_FVW : { SpatialFVStruct* netSpatialFvw = reinterpret_cast<SpatialFVStruct*>(&netBuffer[sizeof(SpatialStruct)]); spatialRvw->isFrozen = netSpatialFvw->isFrozen; netWorldLocation = &netSpatialFvw->worldLocation; netOrientation = &netSpatialFvw->orientation; netVelocityVector = &netSpatialFvw->velocityVector; netAccelerationVector = &netSpatialFvw->accelerationVector; } break; } // end dead rec switch if (netWorldLocation != nullptr) { base::NetHandler::fromNetOrder(&worldLocation->x, netWorldLocation->x); base::NetHandler::fromNetOrder(&worldLocation->y, netWorldLocation->y); base::NetHandler::fromNetOrder(&worldLocation->z, netWorldLocation->z); } else { worldLocation->x = 0; worldLocation->y = 0; worldLocation->z = 0; } if (netOrientation != nullptr) { base::NetHandler::fromNetOrder(&orientation->phi, netOrientation->phi); base::NetHandler::fromNetOrder(&orientation->theta, netOrientation->theta); base::NetHandler::fromNetOrder(&orientation->psi, netOrientation->psi); } else { orientation->phi = 0; orientation->theta = 0; orientation->psi = 0; } if (netVelocityVector != nullptr) { base::NetHandler::fromNetOrder(&velocityVector->xVelocity, netVelocityVector->xVelocity); base::NetHandler::fromNetOrder(&velocityVector->yVelocity, netVelocityVector->yVelocity); base::NetHandler::fromNetOrder(&velocityVector->zVelocity, netVelocityVector->zVelocity); } else { velocityVector->xVelocity = 0; velocityVector->yVelocity = 0; velocityVector->zVelocity = 0; } if (netAccelerationVector != nullptr) { base::NetHandler::fromNetOrder(&accelerationVector->xAcceleration, netAccelerationVector->xAcceleration); base::NetHandler::fromNetOrder(&accelerationVector->yAcceleration, netAccelerationVector->yAcceleration); base::NetHandler::fromNetOrder(&accelerationVector->zAcceleration, netAccelerationVector->zAcceleration); } else { accelerationVector->xAcceleration = 0; accelerationVector->yAcceleration = 0; accelerationVector->zAcceleration = 0; } if (netAngularVelocity != nullptr) { base::NetHandler::fromNetOrder(&angularVelocity->xAngularVelocity, netAngularVelocity->xAngularVelocity); base::NetHandler::fromNetOrder(&angularVelocity->yAngularVelocity, netAngularVelocity->yAngularVelocity); base::NetHandler::fromNetOrder(&angularVelocity->zAngularVelocity, netAngularVelocity->zAngularVelocity); } else { angularVelocity->xAngularVelocity = 0; angularVelocity->yAngularVelocity = 0; angularVelocity->zAngularVelocity = 0; } setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, true); } break; case NetIO::FORCE_IDENTIFIER_AI : { unsigned char* net = reinterpret_cast<unsigned char*>(&netBuffer); physicalEntity->forceIdentifier = ForceIdentifierEnum8( *net ); //std::cout << "Recv force: " << physicalEntity->forceIdentifier << std::endl;; setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, true); } break; } // end -- process attribute switch } // end -- for each attribute pair // Update the basic NIB state data with this new data entityState2Nib(); } }
//------------------------------------------------------------------------------ // updateBasicEntity() -- (Output support) // -- sets the BasicEntity attribute values that need to be updated // // -- We send all published BasicEntity attributes every time. // // The function isPlayerStateUpdateRequired() checking if the player's state // needs to be resent. Therefore, we're not check the individual update // required flags with isAttributeUpdateRequired(), but we do clear them // with setAttributeUpdateRequiredFlag(). // // (Also handles the host to network byte swapping) //------------------------------------------------------------------------------ void Nib::updateBasicEntity( RTI::AttributeHandleValuePairSet* attrs, const double) { if (baseEntity != nullptr) { // Our handler NetIO* netIO = static_cast<NetIO*>(getNetIO()); // Our simulation simulation::Simulation* ourSim = netIO->getSimulation(); // Get the player data playerState2Nib(); // Entity ID if (isAttributeUpdateEnabled(NetIO::ENTITY_IDENTIFIER_AI)) { EntityIdentifierStruct* entityId = &baseEntity->entityIdentifier; entityId->federateIdentifier.siteID = getSiteID(); entityId->federateIdentifier.applicationID = getApplicationID(); entityId->entityNumber = getPlayerID(); //std::cout << "Send Federate ID: (" << entityId->entityNumber << "," << entityId->federateIdentifier.applicationID << "," << entityId->federateIdentifier.siteID << ")" << std::endl; EntityIdentifierStruct netBuffer; base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.applicationID, entityId->federateIdentifier.applicationID ); base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.siteID, entityId->federateIdentifier.siteID ); base::NetHandler::toNetOrder(&netBuffer.entityNumber, entityId->entityNumber ); attrs->add(netIO->getObjectAttributeHandle( NetIO::ENTITY_IDENTIFIER_AI), reinterpret_cast<char*>(&netBuffer), sizeof(EntityIdentifierStruct) ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, false); } // Entity Type if (isAttributeUpdateEnabled(NetIO::ENTITY_TYPE_AI)) { EntityTypeStruct* entityType = &baseEntity->entityType; entityType->entityKind = getEntityKind(); entityType->domain = getEntityDomain(); entityType->countryCode = getEntityCountry(); entityType->category = getEntityCategory(); entityType->subcategory = getEntitySubcategory(); entityType->specific = getEntitySpecific(); entityType->extra = getEntityExtra(); // Network byte order: all bytes except country code which is unsigned short. EntityTypeStruct netBuffer = *entityType; base::NetHandler::toNetOrder(&netBuffer.countryCode, entityType->countryCode ); attrs->add(netIO->getObjectAttributeHandle( NetIO::ENTITY_TYPE_AI), reinterpret_cast<char*>(&netBuffer), sizeof(EntityTypeStruct) ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, false); } // Spatial Structure if (isAttributeUpdateEnabled(NetIO::SPATIAL_AI)) { osg::Vec3d pos = getDrPosition(); osg::Vec3d vel = getDrVelocity(); osg::Vec3d accel = getDrAcceleration(); osg::Vec3d angles = getDrEulerAngles(); osg::Vec3d arates = getDrAngularVelocities(); // NIB's base entity structures SpatialStruct* spatial = &(baseEntity->spatial); SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw); // Net order buffer (used to send the attribute to the RTI) const unsigned int SPATIAL_NET_BUFFER_SIZE = sizeof(SpatialStruct) + sizeof(SpatialRVStruct); unsigned char netBuffer[SPATIAL_NET_BUFFER_SIZE]; SpatialStruct* netSpatial = reinterpret_cast<SpatialStruct*>(&netBuffer[0]); SpatialRVStruct* netSpatialRvw = reinterpret_cast<SpatialRVStruct*>(&netBuffer[sizeof(SpatialStruct)]); // Ref Position double refLat = 0.0; double refLon = 0.0; if (ourSim != nullptr) { refLat = ourSim->getRefLatitude(); refLon = ourSim->getRefLongitude(); } // Convert position vector to Lat/Lon/Alt double alt = 0.0; double simCoord[3] = { 0.0, 0.0, 0.0 }; base::Nav::convertPosVec2LL( refLat, refLon, pos, &simCoord[base::Nav::ILAT], &simCoord[base::Nav::ILON], &alt ); simCoord[base::Nav::IALT] = alt; //std::cout << "RprFom::Nib::entityState2Nib(): simCoord(" << simCoord[Basic::Nav::ILAT] << "," << simCoord[Basic::Nav::ILON] << "," << simCoord[Basic::Nav::IALT] << ")" << std::endl; // Convert to geocentric coordinates double geocPos[3] = { 0.0, 0.0, 0.0 }; double geocVel[3] = { 0.0, 0.0, 0.0 }; double geocAcc[3] = { 0.0, 0.0, 0.0 }; base::Nav::getWorldPosAccVel(simCoord, vel.ptr(), accel.ptr(), geocPos, geocVel, geocAcc); // Dead reckoning algorithm { spatial->deadReckoningAlgorithm = DRM_RVW; netSpatial->deadReckoningAlgorithm = spatial->deadReckoningAlgorithm; } // Is Frozen? { bool simFrz = false; if (ourSim != nullptr) simFrz = ourSim->isFrozen(); if (isFrozen() || simFrz) spatialRvw->isFrozen = RTI::RTI_TRUE; // Is this object or the simulation frozen? else spatialRvw->isFrozen = RTI::RTI_FALSE; netSpatialRvw->isFrozen = spatialRvw->isFrozen; } // World Location { WorldLocationStruct* worldLocation = &spatialRvw->worldLocation; WorldLocationStruct* netWorldLocation = &netSpatialRvw->worldLocation; worldLocation->x = geocPos[base::Nav::IX]; worldLocation->y = geocPos[base::Nav::IY]; worldLocation->z = geocPos[base::Nav::IZ]; base::NetHandler::toNetOrder(&netWorldLocation->x, worldLocation->x); base::NetHandler::toNetOrder(&netWorldLocation->y, worldLocation->y); base::NetHandler::toNetOrder(&netWorldLocation->z, worldLocation->z); } // Velocity vector { VelocityVectorStruct* velocityVector = &spatialRvw->velocityVector; VelocityVectorStruct* netVelocityVector = &netSpatialRvw->velocityVector; velocityVector->xVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IX]); velocityVector->yVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IY]); velocityVector->zVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IZ]); base::NetHandler::toNetOrder(&netVelocityVector->xVelocity, velocityVector->xVelocity); base::NetHandler::toNetOrder(&netVelocityVector->yVelocity, velocityVector->yVelocity); base::NetHandler::toNetOrder(&netVelocityVector->zVelocity, velocityVector->zVelocity); } // Acceleration vector { AccelerationVectorStruct* accelerationVector = &spatialRvw->accelerationVector; AccelerationVectorStruct* netAccelerationVector = &netSpatialRvw->accelerationVector; accelerationVector->xAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IX]); accelerationVector->yAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IY]); accelerationVector->zAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IZ]); base::NetHandler::toNetOrder(&netAccelerationVector->xAcceleration, accelerationVector->xAcceleration); base::NetHandler::toNetOrder(&netAccelerationVector->yAcceleration, accelerationVector->yAcceleration); base::NetHandler::toNetOrder(&netAccelerationVector->zAcceleration, accelerationVector->zAcceleration); } // Orientation { OrientationStruct* orientation = &spatialRvw->orientation; OrientationStruct* netOrientation = &netSpatialRvw->orientation; // Convert Euler angles to geocentric angles double geocAngles[3] = { 0.0, 0.0, 0.0 }; base::Nav::getGeocAngle(simCoord, angles.ptr(), geocAngles); orientation->phi = static_cast<RTI::Float>(geocAngles[base::Nav::IPHI]); orientation->theta = static_cast<RTI::Float>(geocAngles[base::Nav::ITHETA]); orientation->psi = static_cast<RTI::Float>(geocAngles[base::Nav::IPSI]); base::NetHandler::toNetOrder(&netOrientation->phi, orientation->phi); base::NetHandler::toNetOrder(&netOrientation->theta, orientation->theta); base::NetHandler::toNetOrder(&netOrientation->psi, orientation->psi); } // Angular velocity vector (all zeros for now) { AngularVelocityVectorStruct* angularVelocityVector = &spatialRvw->angularVelocity; AngularVelocityVectorStruct* netAngularVelocityVector = &netSpatialRvw->angularVelocity; angularVelocityVector->xAngularVelocity = 0; angularVelocityVector->yAngularVelocity = 0; angularVelocityVector->zAngularVelocity = 0; base::NetHandler::toNetOrder(&netAngularVelocityVector->xAngularVelocity, angularVelocityVector->xAngularVelocity); base::NetHandler::toNetOrder(&netAngularVelocityVector->yAngularVelocity, angularVelocityVector->yAngularVelocity); base::NetHandler::toNetOrder(&netAngularVelocityVector->zAngularVelocity, angularVelocityVector->zAngularVelocity); } attrs->add( netIO->getObjectAttributeHandle(NetIO::SPATIAL_AI), reinterpret_cast<char*>(&netBuffer), SPATIAL_NET_BUFFER_SIZE ); setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, false); } } }
//------------------------------------------------------------------------------ // entityStateManager() -- (Output support) // -- Update the entity object for this NIB(Player) //------------------------------------------------------------------------------ bool Nib::entityStateManager(const LCreal curExecTime) { bool ok = false; // Get the player pointer const Simulation::Player* player = getPlayer(); if (player == nullptr) return ok; // Dummy weapon? const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( player ); if (ww != nullptr) { if (ww->isDummy()) return ok; } if (isPlayerStateUpdateRequired(curExecTime)) { // // Send an entity state PDU // 1) create buffer // 2) set state information // 3) send data // // Get our NetIO and the main simulation NetIO* disIO = static_cast<NetIO*>(getNetIO()); Simulation::Simulation* sim = disIO->getSimulation(); // Capture the player data, reset the dead reckoning and // mark the current time. playerState2Nib(); // --- // Create buffer and cast it as an entity state PDU // --- char pduBuffer[NetIO::MAX_PDU_SIZE]; EntityStatePDU* pdu = (EntityStatePDU*) &pduBuffer[0]; // // Entity state PDU structure // ========================================================= // PDUHeader header; // EntityIdentifierDIS entityID; // uint8_t forceID; // uint8_t numberOfArticulationParameters; // EntityType entityType; // EntityType alternativeType; // VectorDIS entityLinearVelocity; // WorldCoordinates entityLocation; // EulerAngles entityOrientation; // uint32_t appearance; // uint8_t deadReckoningAlgorithm; // uint8_t otherParameters[15]; // VectorDIS DRentityLinearAcceleration; // AngularVelocityVectorDIS DRentityAngularVelocity; // EntityMarking entityMarking; // uint32_t capabilities; // ========================================================= // // --- // Standard header (PDUHeader) // --- pdu->header.protocolVersion = disIO->getVersion(); pdu->header.exerciseIdentifier = disIO->getExerciseID(); pdu->header.PDUType = NetIO::PDU_ENTITY_STATE; pdu->header.protocolFamily = NetIO::PDU_FAMILY_ENTITY_INFO; // if (disIO->getTimeline() == Simulation::NetIO::UTC) pdu->header.timeStamp = disIO->makeTimeStamp( getTimeUtc(), true ); else pdu->header.timeStamp = disIO->makeTimeStamp( getTimeExec(), false ); // pdu->header.status = 0; pdu->header.padding = 0; // --- // Entity ID (EntityIdentifierID) // --- pdu->entityID.simulationID.siteIdentification = getSiteID(); pdu->entityID.simulationID.applicationIdentification = getApplicationID(); pdu->entityID.ID = getPlayerID(); // --- // Force ID: When mapping Player side to force IDs ... // --- if (getSide() == Simulation::Player::BLUE) { // blue's are friendly, ... pdu->forceID = NetIO::FRIENDLY_FORCE; } else if (getSide() == Simulation::Player::RED) { // red's are not, ... pdu->forceID = NetIO::OPPOSING_FORCE; } else if (getSide() == Simulation::Player::WHITE) { // white is neutral, ... pdu->forceID = NetIO::NEUTRAL_FORCE; } else { // and everyone else is type OTHER. pdu->forceID = NetIO::OTHER_FORCE; } // --- // Entity type (EntityType) // --- pdu->entityType.kind = getEntityKind(); pdu->entityType.domain = getEntityDomain(); pdu->entityType.country = getEntityCountry(); pdu->entityType.category = getEntityCategory(); pdu->entityType.subcategory = getEntitySubcategory(); pdu->entityType.specific = getEntitySpecific(); pdu->entityType.extra = getEntityExtra(); // --- // Alternative type (EntityType) // --- pdu->alternativeType.kind = getEntityKind(); pdu->alternativeType.domain = getEntityDomain(); pdu->alternativeType.country = getEntityCountry(); pdu->alternativeType.category = getEntityCategory(); pdu->alternativeType.subcategory = getEntitySubcategory(); pdu->alternativeType.specific = getEntitySpecific(); pdu->alternativeType.extra = getEntityExtra(); // --- // Player position and orientation state data data // 1) All data is geocentric (ECEF) // 2) The playerState2Nib() function, which was called above, captures // the state data and passed the state data to the dead reckoning // system, and we're using this DR captured data. // --- { // --- // Entity linear velocity (VectorDIS) // --- osg::Vec3d geocVel = getDrVelocity(); pdu->entityLinearVelocity.component[0] = static_cast<float>(geocVel[0]); pdu->entityLinearVelocity.component[1] = static_cast<float>(geocVel[1]); pdu->entityLinearVelocity.component[2] = static_cast<float>(geocVel[2]); // --- // Entity location (WorldCoordinates) // --- osg::Vec3d geocPos = getDrPosition(); pdu->entityLocation.X_coord = geocPos[Basic::Nav::IX]; pdu->entityLocation.Y_coord = geocPos[Basic::Nav::IY]; pdu->entityLocation.Z_coord = geocPos[Basic::Nav::IZ]; // --- // Entity orientation (EulerAngles) // --- osg::Vec3d geocAngles = getDrEulerAngles(); pdu->entityOrientation.phi = static_cast<float>(geocAngles[Basic::Nav::IPHI]); pdu->entityOrientation.theta = static_cast<float>(geocAngles[Basic::Nav::ITHETA]); pdu->entityOrientation.psi = static_cast<float>(geocAngles[Basic::Nav::IPSI]); } // --- // Appearance bits generic to all domains (except munitions) // --- { pdu->appearance = 0x0; // --- // Frozen? // --- if ( isFrozen() || sim->isFrozen() ) { pdu->appearance |= FROZEN_BIT; } // Deactive this entity? { if (isMode(Simulation::Player::DELETE_REQUEST) || player->isDead() ) pdu->appearance |= DEACTIVATE_BIT; } // Damage or health? (Bits 3-4) { unsigned int bits = 0; if (getDamage() > 0.9f) bits = 3; // Destroyed or Fatality else if (getDamage() > 0.5) bits = 2; // Moderate else if (getDamage() > 0.0) bits = 1; // Slight else bits = 0; // None pdu->appearance |= (bits << 3); } // Camouflage type // Note: air platform appearance bits 17 and 18 are not used, but we're using them the same as land platforms { unsigned int bits = getCamouflageType(); if (bits > 0 && bits <= 4) { pdu->appearance |= CAMOUFLAGE_BIT; // Land based camouflage bits if (player->isMajorType(Simulation::Player::GROUND_VEHICLE)) { // Subtract one to match DIS camouflage bits. // Our camouflage type for DIS is the camouflage appearance bits // plus one because our camouflage type of zero is no camouflage. bits--; pdu->appearance |= (bits << 17); } } } // Life forms appearance bits if (player->isMajorType(Simulation::Player::LIFE_FORM)) { const Simulation::LifeForm* lf = dynamic_cast<const Simulation::LifeForm*>(player); if (lf != nullptr) { // Health (aka damaged for other domains) same bits (3-4) - this is from the NIB, because it IS // updated // bits 5-8 compliance (not implemented) // bits 9 - 11 unused // bit 12 flashlight (not implemented) // bits 13-15 unused // bits 16 - 19 life form state // data is from the player, because NIB doesn't have actions associated with it { unsigned int bits = 1; // upright, standing still if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_STANDING) bits = 1; // standing else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_WALKING) bits = 2; // walking else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_RUNNING) bits = 3; // running else if (lf->getActionState() == Simulation::LifeForm::KNEELING) bits = 4; // kneeling else if (lf->getActionState() == Simulation::LifeForm::PRONE) bits = 5; // prone else if (lf->getActionState() == Simulation::LifeForm::CRAWLING) bits = 6; // crawling else if (lf->getActionState() == Simulation::LifeForm::SWIMMING) bits = 7; // swimming else if (lf->getActionState() == Simulation::LifeForm::PARACHUTING) bits = 8; // parachuting else if (lf->getActionState() == Simulation::LifeForm::JUMPING) bits = 9; // jumping else if (lf->getActionState() == Simulation::LifeForm::SITTING) bits = 10; // sitting else if (lf->getActionState() == Simulation::LifeForm::SQUATTING) bits = 11; // squatting else if (lf->getActionState() == Simulation::LifeForm::CROUCHING) bits = 12; // crouching else if (lf->getActionState() == Simulation::LifeForm::WADING) bits = 13; // wading else if (lf->getActionState() == Simulation::LifeForm::SURRENDER) bits = 14; // surrender else if (lf->getActionState() == Simulation::LifeForm::DETAINED) bits = 15; // detained else bits = 1; pdu->appearance |= (bits << 16); } // bit 20 unused // bit 21 frozen status (taken care of above) // bits 24 - 25 weapon 1 (not implemented) // bits 26-27 weapon 2 (N/I) // bits 28-29 } } // Common Non-life form appearance bits else { // Smoking? (Bits 5-6) Standard (IST-CF-03-01, May 5, 2003) { unsigned int bits = 0; if (getSmoke() > 0.9f) bits = 3; else if (getSmoke() > 0.5) bits = 2; else if (getSmoke() > 0.0) bits = 1; else bits = 0; pdu->appearance |= (bits << 5); } // Flames? (Bit 15) Standard (IST-CF-03-01, May 5, 2003) { if (getFlames() > 0.5f) pdu->appearance |= FLAMES_BIT; } // Power plant status bit (just leave ON for now) pdu->appearance |= POWER_PLANT_BIT; } } // --- // Dead reckoning algorithm // --- pdu->deadReckoningAlgorithm = static_cast<unsigned char>(getDeadReckoning()); // --- // Other parameters // --- for (unsigned int i=0; i<15; i++) { pdu->otherParameters[i] = 0; } // --- // Dead reckoning information // --- { // --- // Dead reckoning linear acceleration (VectorDIS) // --- osg::Vec3d geocAcc = getDrAcceleration(); pdu->DRentityLinearAcceleration.component[0] = static_cast<float>(geocAcc[0]); pdu->DRentityLinearAcceleration.component[1] = static_cast<float>(geocAcc[1]); pdu->DRentityLinearAcceleration.component[2] = static_cast<float>(geocAcc[2]); // --- // Dead reckoning angular velocity (AngularVelocityVectorDIS) // --- osg::Vec3d geocAngVel = getDrAngularVelocities(); pdu->DRentityAngularVelocity.x_axis = static_cast<float>(geocAngVel[Basic::Nav::IX]); pdu->DRentityAngularVelocity.y_axis = static_cast<float>(geocAngVel[Basic::Nav::IY]); pdu->DRentityAngularVelocity.z_axis = static_cast<float>(geocAngVel[Basic::Nav::IZ]); } // --- // Entity marking (EntityMarking) // --- { const char* const pName = getPlayerName(); size_t nameLen = std::strlen(pName); for (unsigned int i = 0; i < EntityMarking::BUFF_SIZE; i++) { if (i < nameLen) { pdu->entityMarking.marking[i] = pName[i]; } else { pdu->entityMarking.marking[i] = '\0'; } } pdu->entityMarking.characterSet = 1; } // --- // Capabilities // --- pdu->capabilites = 0x0; // --- // Articulation parameters // --- pdu->numberOfArticulationParameters = manageArticulationParameters(pdu); // Size of the PDU package unsigned short length = sizeof(EntityStatePDU) + (pdu->numberOfArticulationParameters * sizeof(VpArticulatedPart)); pdu->header.length = length; if (Basic::NetHandler::isNotNetworkByteOrder()) pdu->swapBytes(); ok = disIO->sendData( reinterpret_cast<char*>(pdu), length ); } return ok; }
//------------------------------------------------------------------------------ // munitionDetonationMsgFactory() -- (Output) Munition detonation message factory //------------------------------------------------------------------------------ bool Nib::munitionDetonationMsgFactory(const LCreal) { // Dummy weapon? const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( getPlayer() ); if (ww != 0) { if (ww->isDummy()) return true; } bool ok = true; //std::cout << "NetIO::munitionDetonationMsgFactory() HERE!!" << std::endl; // Get our NetIO NetIO* disIO = (NetIO*)(getNetIO()); // If our NIB's player just detonated, then it must be a weapon! Simulation::Weapon* mPlayer = dynamic_cast<Simulation::Weapon*>(getPlayer()); if (mPlayer == 0) return false; // Ok, we have the weapon, now get the firing and target players Simulation::Player* tPlayer = mPlayer->getTargetPlayer(); Simulation::Player* fPlayer = mPlayer->getLaunchVehicle(); if (fPlayer == 0) return false; // --- // PDU header // --- DetonationPDU pdu; pdu.header.protocolVersion = disIO->getVersion(); pdu.header.PDUType = NetIO::PDU_DETONATION; pdu.header.protocolFamily = NetIO::PDU_FAMILY_WARFARE; pdu.header.length = sizeof(DetonationPDU); pdu.header.exerciseIdentifier = disIO->getExerciseID(); pdu.header.timeStamp = disIO->timeStamp(); pdu.header.status = 0; pdu.header.padding = 0; // --- // Set the PDU data with the firing (launcher) player's id // --- pdu.firingEntityID.ID = fPlayer->getID(); pdu.firingEntityID.simulationID.siteIdentification = getSiteID(); pdu.firingEntityID.simulationID.applicationIdentification = getApplicationID(); // --- // Set the PDU data with the munition's ID // --- pdu.munitionID.ID = mPlayer->getID(); pdu.munitionID.simulationID.siteIdentification = getSiteID(); pdu.munitionID.simulationID.applicationIdentification = getApplicationID(); // --- // Set the PDU data with the target's ID // --- { bool tOk = false; if (tPlayer != 0) { pdu.targetEntityID.ID = tPlayer->getID(); if (tPlayer->isLocalPlayer()) { // Local player, use our site/app/exerc IDs pdu.targetEntityID.simulationID.siteIdentification = getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = getApplicationID(); tOk = true; } else { // Networked player, use its NIB's IDs const Nib* fNIB = dynamic_cast<const Nib*>( tPlayer->getNib() ); if (fNIB != 0) { pdu.targetEntityID.simulationID.siteIdentification = fNIB->getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = fNIB->getApplicationID(); tOk = true; } } } if (!tOk) { pdu.targetEntityID.ID = 0; pdu.targetEntityID.simulationID.siteIdentification = 0; pdu.targetEntityID.simulationID.applicationIdentification = 0; } } // --- // Event ID // --- pdu.eventID.simulationID.siteIdentification = getSiteID(); pdu.eventID.simulationID.applicationIdentification = getApplicationID(); pdu.eventID.eventNumber = mPlayer->getReleaseEventID(); // --- // Location & Velocity // --- // World Coordinates osg::Vec3d geocPos = mPlayer->getGeocPosition(); pdu.location.X_coord = geocPos[Basic::Nav::IX]; pdu.location.Y_coord = geocPos[Basic::Nav::IY]; pdu.location.Z_coord = geocPos[Basic::Nav::IZ]; // Velocity osg::Vec3d geocVel = mPlayer->getGeocVelocity(); pdu.velocity.component[0] = (float)geocVel[Basic::Nav::IX]; pdu.velocity.component[1] = (float)geocVel[Basic::Nav::IY]; pdu.velocity.component[2] = (float)geocVel[Basic::Nav::IZ]; // --- // Burst // --- pdu.burst.munition.kind = getEntityKind(); pdu.burst.munition.domain = getEntityDomain(); pdu.burst.munition.country = getEntityCountry(); pdu.burst.munition.category = getEntityCategory(); pdu.burst.munition.subcategory = getEntitySubcategory(); pdu.burst.munition.specific = getEntitySpecific(); pdu.burst.munition.extra = getEntityExtra(); pdu.burst.warhead = 0; pdu.burst.fuse = 0;; pdu.burst.quantity = 1; pdu.burst.rate = 0; // --- // Location // --- osg::Vec3 lpos = mPlayer->getDetonationLocation(); pdu.locationInEntityCoordinates.component[0] = (float) lpos[0]; pdu.locationInEntityCoordinates.component[1] = (float) lpos[1]; pdu.locationInEntityCoordinates.component[2] = (float) lpos[2]; // --- // Results // --- pdu.detonationResult = (unsigned char)( mPlayer->getDetonationResults() ); pdu.numberOfArticulationParameters = 0; //std::cout << "NetIO::munitionDetonationMsgFactory() results: " << int(pdu.detonationResult) << std::endl; //pdu.dumpData(); // --- // Send the PDU // --- if (Basic::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes(); ok = disIO->sendData((char*)&pdu,sizeof(pdu)); // Set the detonation message sent flag so that we don't do this again. setDetonationMessageSent(true); return ok; }
//------------------------------------------------------------------------------ // entityState2Nib() -- (Input support) // Transfers data from the incoming entity attributes to the basic // NIB class variables. //------------------------------------------------------------------------------ void Nib::entityState2Nib() { if (isAttributeUpdateRequired(NetIO::ENTITY_IDENTIFIER_AI)) { setPlayerID(baseEntity->entityIdentifier.entityNumber); setSiteID(baseEntity->entityIdentifier.federateIdentifier.siteID); setApplicationID(baseEntity->entityIdentifier.federateIdentifier.applicationID); setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, false); haveEntityIdFlg = true; } if (isAttributeUpdateRequired(NetIO::ENTITY_TYPE_AI)) { setEntityType( baseEntity->entityType.entityKind, baseEntity->entityType.domain, baseEntity->entityType.countryCode, baseEntity->entityType.category, baseEntity->entityType.subcategory, baseEntity->entityType.specific, baseEntity->entityType.extra ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, false); haveEntityTypeFlg = true; } if (isAttributeUpdateRequired(NetIO::SPATIAL_AI)) { // NIB's base entity structures //SpatialStruct* spatial = &(baseEntity->spatial); SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw); // Set the freeze flag freeze(spatialRvw->isFrozen != 0); // Get the geocentric position, velocity and acceleration osg::Vec3d geocPos; geocPos[base::Nav::IX] = spatialRvw->worldLocation.x; geocPos[base::Nav::IY] = spatialRvw->worldLocation.y; geocPos[base::Nav::IZ] = spatialRvw->worldLocation.z; osg::Vec3d geocVel; geocVel[base::Nav::IX] = spatialRvw->velocityVector.xVelocity; geocVel[base::Nav::IY] = spatialRvw->velocityVector.yVelocity; geocVel[base::Nav::IZ] = spatialRvw->velocityVector.zVelocity; osg::Vec3d geocAcc; geocAcc[base::Nav::IX] = spatialRvw->accelerationVector.xAcceleration; geocAcc[base::Nav::IY] = spatialRvw->accelerationVector.yAcceleration; geocAcc[base::Nav::IZ] = spatialRvw->accelerationVector.zAcceleration; // Get orientation orientation and rates osg::Vec3d geocAngles; geocAngles[base::Nav::IPHI] = spatialRvw->orientation.phi; geocAngles[base::Nav::ITHETA] = spatialRvw->orientation.theta; geocAngles[base::Nav::IPSI] = spatialRvw->orientation.psi; osg::Vec3d arates(0.0, 0.0, 0.0); // (re)initialize the dead reckoning function double diffTime(0.0); resetDeadReckoning( RVW_DRM, geocPos, geocVel, geocAcc, geocAngles, arates, diffTime); haveWorldLocationFlg = true; haveOrientationFlg = true; setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, false); } // PhysicalEntity pointer PhysicalEntity* physicalEntity = dynamic_cast<PhysicalEntity*>(baseEntity); if (physicalEntity != nullptr) { if (isAttributeUpdateRequired(NetIO::FORCE_IDENTIFIER_AI)) { // Side: When mapping Force ID to Player Side ... if (physicalEntity->forceIdentifier == FRIENDLY) { // Friendly's are blue, ... setSide(simulation::Player::BLUE); } else if (physicalEntity->forceIdentifier == OPPOSING) { // opposing side is red, ... setSide(simulation::Player::RED); } else if (physicalEntity->forceIdentifier == NEUTRAL) { // Neutrals are white, ... setSide(simulation::Player::WHITE); } else { // and everyone else is gray. setSide(simulation::Player::GRAY); } setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, false); } } setMode(simulation::Player::ACTIVE); setTimeExec( (double) getNetIO()->getCurrentTime() ); }
//------------------------------------------------------------------------------ // weaponFireMsgFactory() -- (Output support) Weapon fire message factory //------------------------------------------------------------------------------ bool Nib::weaponFireMsgFactory(const LCreal) { bool ok = true; //std::cout << "NetIO::weaponFireMsgFactory() HERE!!" << std::endl; // Get our NetIO NetIO* disIO = (NetIO*)(getNetIO()); //Simulation* sim = disIO->getSimulation(); // Set the NIB mode so that we don't do this again. setMode(Simulation::Player::ACTIVE); // Our NIB's player is a weapon that just became active Simulation::Weapon* mPlayer = (Simulation::Weapon*)(getPlayer()); // Ok, we have the weapon, now get the firing and target players Simulation::Player* tPlayer = mPlayer->getTargetPlayer(); Simulation::Player* fPlayer = mPlayer->getLaunchVehicle(); if (fPlayer == 0) return false; // --- // PDU header // --- FirePDU pdu; pdu.header.protocolVersion = disIO->getVersion(); pdu.header.exerciseIdentifier = disIO->getExerciseID(); pdu.header.PDUType = NetIO::PDU_FIRE; pdu.header.protocolFamily = NetIO::PDU_FAMILY_WARFARE; pdu.header.timeStamp = disIO->timeStamp(); pdu.header.length = sizeof(FirePDU); // --- // Set the PDU data with the firing (launcher) player's id // --- pdu.firingEntityID.ID = fPlayer->getID(); pdu.firingEntityID.simulationID.siteIdentification = disIO->getSiteID(); pdu.firingEntityID.simulationID.applicationIdentification = disIO->getApplicationID(); // --- // Set the PDU data with the munition's ID // --- pdu.munitionID.ID = mPlayer->getID(); pdu.munitionID.simulationID.siteIdentification = disIO->getSiteID(); pdu.munitionID.simulationID.applicationIdentification = disIO->getApplicationID(); // --- // Set the PDU data with the target's ID // --- { bool tOk = false; if (tPlayer != 0) { pdu.targetEntityID.ID = tPlayer->getID(); if (tPlayer->isLocalPlayer()) { // Local player, use our site/app/exerc IDs pdu.targetEntityID.simulationID.siteIdentification = disIO->getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = disIO->getApplicationID(); tOk = true; } else { const Nib* fNIB = dynamic_cast<const Nib*>( tPlayer->getNib() ); if (fNIB != 0) { // Networked player, use it's NIB's IDs pdu.targetEntityID.simulationID.siteIdentification = fNIB->getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = fNIB->getApplicationID(); tOk = true; } } } if (!tOk) { // Networked player, use it's NIB's IDs pdu.targetEntityID.ID = 0; pdu.targetEntityID.simulationID.siteIdentification = 0; pdu.targetEntityID.simulationID.applicationIdentification = 0; } } // --- // Event ID // --- pdu.eventID.simulationID.siteIdentification = disIO->getSiteID(); pdu.eventID.simulationID.applicationIdentification = disIO->getApplicationID(); pdu.eventID.eventNumber = mPlayer->getReleaseEventID(); // --- // Location & Velociy // --- // World Coordinates osg::Vec3d geocPos = mPlayer->getGeocPosition(); pdu.location.X_coord = geocPos[Basic::Nav::IX]; pdu.location.Y_coord = geocPos[Basic::Nav::IY]; pdu.location.Z_coord = geocPos[Basic::Nav::IZ]; // Velocity osg::Vec3d geocVel = mPlayer->getGeocVelocity(); pdu.velocity.component[0] = (float)geocVel[Basic::Nav::IX]; pdu.velocity.component[1] = (float)geocVel[Basic::Nav::IY]; pdu.velocity.component[2] = (float)geocVel[Basic::Nav::IZ]; // --- // Burst // --- pdu.burst.munision.kind = getEntityKind(); pdu.burst.munision.domain = getEntityDomain(); pdu.burst.munision.country = getEntityCountry(); pdu.burst.munision.category = getEntityCategory(); pdu.burst.munision.subcategory = getEntitySubcategory(); pdu.burst.munision.specific = getEntitySpecific(); pdu.burst.munision.extra = getEntityExtra(); pdu.burst.warhead = 0; pdu.burst.fuse = 0;; pdu.burst.quantity = 1; pdu.burst.rate = 0; // --- // Range and fire index // --- pdu.fireMissionIndex = 0; pdu.range = 0.0; //pdu.dumpData(); //std::cout << "NetIO::weaponFireMsgFactory() fired:"; //std::cout << "(" << pdu.firingEntityID.ID; //std::cout << "," << pdu.firingEntityID.simulationID.applicationIdentification ; //std::cout << "," << pdu.firingEntityID.simulationID.siteIdentification; //std::cout << ") munision:"; //std::cout << "(" << pdu.munitionID.ID; //std::cout << "," << pdu.munitionID.simulationID.applicationIdentification ; //std::cout << "," << pdu.munitionID.simulationID.siteIdentification; //std::cout << ")" << std::endl; if (Basic::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes(); ok = disIO->sendData((char*)&pdu,sizeof(pdu)); return ok; }
//------------------------------------------------------------------------------ // Manage the articulated parameters and attached parts //------------------------------------------------------------------------------ unsigned char Nib::manageArticulationParameters(EntityStatePDU* const pdu) { unsigned char cnt = 0; NetIO* const disIO = static_cast<NetIO*>(getNetIO()); // First articulation parameter is just after the main PDU unsigned char *p = (reinterpret_cast<unsigned char *>(pdu)) + sizeof(*pdu); VpArticulatedPart* ap = reinterpret_cast<VpArticulatedPart*>(p); // --- // Air Vehicle articulated parts and attachments // --- if ( getPlayer()->isMajorType(Simulation::Player::AIR_VEHICLE) ) { // Check wing sweep angle. if (getAPartWingSweepCnt() > 0) { // fill the articulation parameter structure ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartWingSweepCnt() & 0xff); ap->id = 0; ap->parameterType = (VpArticulatedPart::WING_SWEEP + VpArticulatedPart::AZIMUTH); ap->parameterValue.value[0] = static_cast<float>(getAPartWingSweep()); // radians ap->parameterValue.value[1] = 0; // Update part count & pointer cnt++; ap++; } // Check landing gear position. if (getAPartGearPosCnt() > 0) { // fill the articulation parameter structure ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartGearPosCnt() & 0xff); ap->id = 0; ap->parameterType = (VpArticulatedPart::LANDING_GEAR + VpArticulatedPart::POSITION); ap->parameterValue.value[0] = static_cast<float>(getAPartPartGearPos())/100.0f; ap->parameterValue.value[1] = 0; // Update part count & pointer cnt++; ap++; } // Check weapon bay door position (send out both doors) if (getAPartBayDoorCnt() > 0) { // Left door ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartBayDoorCnt() & 0xff); ap->id = 0; ap->parameterType = (VpArticulatedPart::LEFT_WEAPON_BAY_DOOR + VpArticulatedPart::POSITION); ap->parameterValue.value[0] = static_cast<float>(getAPartBayDoorPos())/100.0f; ap->parameterValue.value[1] = 0; // Update part count & pointer cnt++; ap++; // Right door ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartBayDoorCnt() & 0xff); ap->id = 0; ap->parameterType = (VpArticulatedPart::RIGHT_WEAPON_BAY_DOOR + VpArticulatedPart::POSITION); ap->parameterValue.value[0] = static_cast<float>(getAPartBayDoorPos())/100.0f; ap->parameterValue.value[1] = 0; // Update part count & pointer cnt++; ap++; } } // --- // Ground Vehicle articulated parts and attachments // --- else if ( getPlayer()->isMajorType(Simulation::Player::GROUND_VEHICLE) ) { // Check launcher elevation angle if (getAPartLauncherElevationCnt() > 0) { // fill the articulation parameter structure ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartLauncherElevationCnt() & 0xff); ap->id = 0; ap->parameterType = (VpArticulatedPart::PRIMARY_LAUNCHER_1 + VpArticulatedPart::ELEVATION); ap->parameterValue.value[0] = static_cast<float>( getAPartLauncherElevation() ); ap->parameterValue.value[1] = 0; // Update part count & pointer cnt++; ap++; } // Check attached missiles unsigned int n = getAPartNumberAttachedNumMissiles(); for (unsigned int i = 0; i < n; i++) { const Simulation::Missile* msl = getAPartAttachedMissile(i+1); // Find the missile's entity type if (apartMslTypes[i] == nullptr) { const Ntm* ntm = dynamic_cast<const Ntm*>( disIO->findNetworkTypeMapper(msl) ); if (ntm != nullptr) { // found the NTM for the missile -- and it must be a DIS NTM apartMslTypes[i] = dynamic_cast<const Ntm*>(ntm); if (apartMslTypes[i] != nullptr) apartMslTypes[i]->ref(); } } // We must have the missile's entity type to send the attached part ... if (apartMslTypes[i] != nullptr) { // fill the articulation parameter structure ap->parameterTypeDesignator = VpArticulatedPart::ATTACHED_PART; ap->changeIndicator = static_cast<unsigned char>(getAPartAttacheMissileChangeCnt(i+1) & 0xff); ap->id = 1; // ATTACHED to LAUNCHER (above) ap->parameterType = (i+1); // Station number if (msl->isMode(Simulation::Player::LAUNCHED)) { ap->parameterValue.entityType.kind = 0; ap->parameterValue.entityType.domain = 0; ap->parameterValue.entityType.country = 0; ap->parameterValue.entityType.category = 0; ap->parameterValue.entityType.subcategory = 0; ap->parameterValue.entityType.specific = 0; ap->parameterValue.entityType.extra = 0; } else { ap->parameterValue.entityType.kind = apartMslTypes[i]->getEntityKind(); ap->parameterValue.entityType.domain = apartMslTypes[i]->getEntityDomain(); ap->parameterValue.entityType.country = apartMslTypes[i]->getEntityCountry(); ap->parameterValue.entityType.category = apartMslTypes[i]->getEntityCategory(); ap->parameterValue.entityType.subcategory = apartMslTypes[i]->getEntitySubcategory(); ap->parameterValue.entityType.specific = apartMslTypes[i]->getEntitySpecific(); ap->parameterValue.entityType.extra = apartMslTypes[i]->getEntityExtra(); } // Update part count & pointer cnt++; ap++; } } } return cnt; }
//------------------------------------------------------------------------------ // IffManager() -- (Output support) IFF manager //------------------------------------------------------------------------------ bool Nib::IffManager(const double curExecTime) { NetIO* disIO = static_cast<NetIO*>(getNetIO()); const base::Pair* pair = getPlayer()->getRadioByType(typeid(models::Iff)); // OK if the player has an IFF transponder and we're the correct version. bool ok = (disIO->getVersion() >= NetIO::VERSION_1278_1A) && (pair != nullptr); if (ok) { const models::Iff* iffSystem = static_cast<const models::Iff*>(pair->object()); if (isIffUpdateRequired(curExecTime, iffSystem)) { // Standard header stuff IffAtcNavaidsPDU pdu; pdu.header.protocolVersion = disIO->getVersion(); pdu.header.exerciseIdentifier = disIO->getExerciseID(); pdu.header.PDUType = NetIO::PDU_IFF_ATC_NAVAIDS; pdu.header.protocolFamily = NetIO::PDU_FAMILY_DIS_EMISSION_REG; pdu.header.timeStamp = disIO->timeStamp(); pdu.header.length = sizeof(IffAtcNavaidsPDU); // Entity ID pdu.emittingEntityID.simulationID.siteIdentification = getSiteID(); pdu.emittingEntityID.simulationID.applicationIdentification = getApplicationID(); pdu.emittingEntityID.ID = getPlayerID(); // Location (default is center of parent entity) pdu.location.component[0] = 0; pdu.location.component[1] = 0; pdu.location.component[2] = 0; // System ID (for now just use a standard Mark X11; upgrade to type from IFF later) pdu.systemID.systemType = 1; // Mark X11 pdu.systemID.systemName = 2; // Mark X11 pdu.systemID.systemMode = 0; // Other pdu.systemID.options = iffOptions; // Option bits // Functional operational data pdu.operationalData.systemStatus = iffFunOpData->systemStatus; pdu.operationalData.alternateParam4 = iffFunOpData->alternateParam4; pdu.operationalData.informationLayers = iffFunOpData->informationLayers; pdu.operationalData.modifier = iffFunOpData->modifier; pdu.operationalData.param1 = iffFunOpData->param1; pdu.operationalData.param2 = iffFunOpData->param2; pdu.operationalData.param3 = iffFunOpData->param3; pdu.operationalData.param4 = iffFunOpData->param4; pdu.operationalData.param5 = iffFunOpData->param5; pdu.operationalData.param6 = iffFunOpData->param6; // Event ID pdu.eventID.simulationID.siteIdentification = disIO->getSiteID(); pdu.eventID.simulationID.applicationIdentification = disIO->getApplicationID(); pdu.eventID.eventNumber = disIO->getNewIffEventID(); //pdu.dumpData(); if (base::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes(); ok = disIO->sendData(reinterpret_cast<char*>(&pdu), sizeof(pdu)); iffLastExecTime = curExecTime; } } return ok; }
//------------------------------------------------------------------------------ // 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; }
//------------------------------------------------------------------------------ // isPlayerStateUpdateRequired() -- check to see if an update is required //------------------------------------------------------------------------------ bool Nib::isPlayerStateUpdateRequired(const double curExecTime) { enum { NO, YES, UNSURE } result = UNSURE; // --- // 1) Make sure that we have a valid player and entity type // --- const models::Player* player = getPlayer(); if (player == nullptr || isEntityTypeInvalid()) result = NO; // --- // 2) Mode changes // --- if ( (result == UNSURE) && isNotMode( player->getMode()) ) result = YES; // 2-a) NIB is being deleted, send one more update to deactivate the entity if ( (result == UNSURE) && isMode( models::Player::DELETE_REQUEST ) ) result = YES; // --- // 3) When we're a local player, check for one of the following ... // --- if ( (result == UNSURE) && player->isLocalPlayer()) { //double drTime = curExecTime - getTimeExec(); models::SynchronizedState playerState = player->getSynchronizedState(); const double drTime = static_cast<double>(playerState.getTimeExec()) - getTimeExec(); // 3-a) Freeze flag has changed if ( (player->isFrozen() && isNotFrozen()) || (!player->isFrozen() && isFrozen()) ) { result = YES; } // 3-b) Max DR timeout if (result == UNSURE) { if ( drTime >= getNetIO()->getMaxTimeDR(this) ) { result = YES; } } // 3-c) Appearance has changed if (result == UNSURE && (player->getDamage() != getDamage() || player->getSmoke() != getSmoke() || player->getFlames() != getFlames() || player->getCamouflageType() != getCamouflageType() ) ) { result = YES; } // 3-d) Check dead reckoning errors if (result == UNSURE && isNotFrozen()) { // Compute our dead reckoned position and angles, which are // based on our last packet sent. base::Vec3d drPos; base::Vec3d drAngles; mainDeadReckoning(drTime, &drPos, &drAngles); // 3-d-1) Position error if (!player->isPositionFrozen() && !player->isAltitudeFrozen()) { // max position error (meters) const double maxPosErr = getNetIO()->getMaxPositionErr(this); const double maxPosErr2 = maxPosErr*maxPosErr; // squared // Check if the length of the position error (squared) is greater // than the max error (squared) //base::Vec3d ppos = player->getGeocPosition(); const base::Vec3d ppos = playerState.getGeocPosition(); const base::Vec3d errPos = drPos - ppos; if (errPos.length2() >= maxPosErr2) { result = YES; } } // 3-d-2) Orientation error if (result == UNSURE && !player->isAttitudeFrozen()) { // max angle error (radians) const double maxAngleErr = getNetIO()->getMaxOrientationErr(this); // Compute angular error //base::Vec3 errAngles = drAngles - player->getGeocEulerAngles(); base::Vec3d errAngles = drAngles - playerState.getGeocEulerAngles(); // Check if any angle error is greater than the max error errAngles[0] = std::fabs( base::angle::aepcdDeg(errAngles[0]) ); if (errAngles[0] >= maxAngleErr) result = YES; errAngles[1] = std::fabs( base::angle::aepcdDeg(errAngles[1]) ); if (errAngles[1] >= maxAngleErr) result = YES; errAngles[2] = std::fabs( base::angle::aepcdDeg(errAngles[2]) ); if (errAngles[2] >= maxAngleErr) result = YES; } } } // --- // 4) Check for air vehicle articulated and attached parts (always check this) // --- if ( player != nullptr && player->isMajorType(models::Player::AIR_VEHICLE) ) { const models::AirVehicle* av = static_cast<const models::AirVehicle*>(player); // (4-a) Check wing sweep angle. We only send out wing sweep as // an part if the position is greater than zero or if we've previously been // sending the wing sweep (count > 0). { const double angle = av->getWingSweepAngle(); // radians if (angle > 0 || apartWingSweepCnt > 0) { // Check if the angle has changed. if (angle != apartWingSweep) { apartWingSweep = angle; apartWingSweepCnt++; result = YES; } } } // (4-b) Check landing gear position. We only send out gear position as // an part if the gear is not up (pos != 0) or if we've previously been // sending the gear position (count > 0). { const double pos = av->getLandingGearPosition(); // (0% up; 100% down) if (pos > 0 || apartGearPosCnt > 0) { // Check if the pos has changed. if (pos != apartLandingGear) { apartLandingGear = pos; apartGearPosCnt++; result = YES; } } } // (4-c) Check bay door position. We only send out bay door posiiton as // an part if the door is not closed (pos != 0) or if we've previously been // sending the door position (count > 0). { const double pos = av->getWeaponBayDoorPosition(); // % (0% closed; 100% open) if (pos > 0 || apartBayDoorCnt > 0) { // Check if the pos has changed. if (pos != apartBayDoor) { apartBayDoor = pos; apartBayDoorCnt++; result = YES; } } } } // --- // 5) Check for ground vehicle articulated and attached parts (always check this) // --- if ( player != nullptr && player->isMajorType(models::Player::GROUND_VEHICLE) ) { const models::GroundVehicle* gv = static_cast<const models::GroundVehicle*>(player); // (5-a) Send launcher elevation angle and for an attached missile // (on SamVehicles and Artillery only) if ( gv->isClassType(typeid(models::SamVehicle)) || gv->isClassType(typeid(models::Artillery)) ) { const double angle = gv->getLauncherPosition(); // (radians) // First pass -- if (apartLnchrElevCnt == 0) { // find all missiles missiles const models::StoresMgr* sm = gv->getStoresManagement(); if (sm != nullptr) { const base::PairStream* stores = sm->getStores(); if (stores != nullptr) { const base::List::Item* item = stores->getFirstItem(); while (item != nullptr && apartNumMissiles < MAX_AMSL) { const auto pair = static_cast<const base::Pair*>(item->getValue()); if (pair != nullptr) { const auto msl = dynamic_cast<const models::Missile*>( pair->object() ); if (msl != nullptr) { // Save the pointer to the missile, set the missile's change count to 1, // and up the missile count msl->ref(); apartMsl[apartNumMissiles] = msl; apartMslAttached[apartNumMissiles] = !(msl->isMode(models::Player::LAUNCHED)); apartMslCnt[apartNumMissiles] = 1; apartNumMissiles++; } } item = item->getNext(); } stores->unref(); stores = nullptr; } } // If we have missile then set the launcher angle if (apartNumMissiles > 0) { apartLnchrElev = angle; apartLnchrElevCnt++; } } // If we have the launcher angle and missiles then check for changes if (apartLnchrElevCnt != 0) { // Check if the pos has changed if (angle != apartLnchrElev) { apartLnchrElev = angle; apartLnchrElevCnt++; result = YES; } // Check all missiles for change in launched status for (unsigned int i = 0; i < apartNumMissiles; i++) { bool attached = !(apartMsl[i]->isMode(models::Player::LAUNCHED)); if (attached != apartMslAttached[i]) { // There's been a change in status apartMslAttached[i] = attached; apartMslCnt[i]++; } } } } } // --- // 6) When we're a network player -- Update when the exec time of the // last input (player's NIB) is different that our exec time. // --- if ( (result == UNSURE) && player->isNetworkedPlayer() ) { const auto playerNib = dynamic_cast<const Nib*>(player->getNib()); if (playerNib->getTimeExec() != getTimeExec()) { result = YES; } } return (result == YES); }