From 1f95d0c017de6f613465b04d7cc4943679b91e43 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 23 Jan 2014 12:47:27 -0800 Subject: [PATCH] have avatar-mixer report avatar kills to all avatars --- assignment-client/src/avatars/AvatarMixer.cpp | 23 ++++++++++++-- assignment-client/src/avatars/AvatarMixer.h | 2 ++ interface/src/DatagramProcessor.cpp | 17 +++++++--- interface/src/avatar/AvatarManager.cpp | 15 +++++++++ interface/src/avatar/AvatarManager.h | 2 ++ interface/src/avatar/MyAvatar.cpp | 15 +++++++++ interface/src/avatar/MyAvatar.h | 4 ++- libraries/shared/src/NodeList.cpp | 31 +++---------------- libraries/shared/src/NodeList.h | 3 +- libraries/shared/src/PacketHeaders.h | 2 +- 10 files changed, 78 insertions(+), 36 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 56464d2415..ccd14acc04 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -30,7 +30,8 @@ const unsigned int AVATAR_DATA_SEND_INTERVAL_USECS = (1 / 60.0) * 1000 * 1000; AvatarMixer::AvatarMixer(const unsigned char* dataBuffer, int numBytes) : ThreadedAssignment(dataBuffer, numBytes) { - + // make sure we hear about node kills so we can tell the other nodes + connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); } unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) { @@ -116,6 +117,21 @@ void broadcastAvatarData() { } } +void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { + if (killedNode->getType() == NODE_TYPE_AGENT + && killedNode->getLinkedData()) { + // this was an avatar we were sending to other people + // send a kill packet for it to our other nodes + unsigned char packetData[MAX_PACKET_SIZE]; + int numHeaderBytes = populateTypeAndVersion(packetData, PACKET_TYPE_KILL_AVATAR); + + QByteArray rfcUUID = killedNode->getUUID().toRfc4122(); + memcpy(packetData + numHeaderBytes, rfcUUID.constData(), rfcUUID.size()); + + NodeList::getInstance()->broadcastToNodes(packetData, numHeaderBytes + NUM_BYTES_RFC4122_UUID, &NODE_TYPE_AGENT, 1); + } +} + void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { NodeList* nodeList = NodeList::getInstance(); @@ -136,7 +152,10 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc break; } } - case PACKET_TYPE_KILL_NODE: + case PACKET_TYPE_KILL_AVATAR: { + nodeList->processKillNode(dataByteArray); + break; + } default: // hand this off to the NodeList nodeList->processNodeData(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index c2158fad1c..2da0ed98eb 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -19,6 +19,8 @@ public: public slots: /// runs the avatar mixer void run(); + + void nodeKilled(SharedNodePointer killedNode); void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); }; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 13d43c2f81..04dd7618e1 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -89,7 +89,8 @@ void DatagramProcessor::processDatagrams() { application->_metavoxels.processData(QByteArray((const char*) incomingPacket, bytesReceived), senderSockAddr); break; - case PACKET_TYPE_BULK_AVATAR_DATA: { + case PACKET_TYPE_BULK_AVATAR_DATA: + case PACKET_TYPE_KILL_AVATAR: { // update having heard from the avatar-mixer and record the bytes received SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr); @@ -97,15 +98,21 @@ void DatagramProcessor::processDatagrams() { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->recordBytesReceived(bytesReceived); + QByteArray datagram(reinterpret_cast(incomingPacket), bytesReceived); - QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", - Q_ARG(const QByteArray&, - QByteArray(reinterpret_cast(incomingPacket), bytesReceived))); + if (incomingPacket[0] == PACKET_TYPE_BULK_AVATAR_DATA) { + QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", + Q_ARG(const QByteArray&, datagram)); + } else { + // this is an avatar kill, pass it to the application AvatarManager + QMetaObject::invokeMethod(&application->getAvatarManager(), "processKillAvatar", + Q_ARG(const QByteArray&, datagram)); + } } application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived); break; - } + } case PACKET_TYPE_DATA_SERVER_GET: case PACKET_TYPE_DATA_SERVER_PUT: case PACKET_TYPE_DATA_SERVER_SEND: diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index f9a3422fb5..f5090343f2 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -51,4 +51,19 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram) { bytesRead += matchingAvatar->parseData(avatarData, datagram.size() - bytesRead); } +} + +void AvatarManager::processKillAvatar(const QByteArray& datagram) { + // read the node id + QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(reinterpret_cast + (datagram.data())), + NUM_BYTES_RFC4122_UUID)); + + // kill the avatar with that UUID from our hash, if it exists + _hash.remove(nodeUUID); +} + +void AvatarManager::clearHash() { + // clear the AvatarManager hash - typically happens on the removal of the avatar-mixer + _hash.clear(); } \ No newline at end of file diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 5ea7607660..dde84ba62b 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -20,6 +20,8 @@ public: AvatarManager(QObject* parent = 0); public slots: void processAvatarMixerDatagram(const QByteArray& datagram); + void processKillAvatar(const QByteArray& datagram); + void clearHash(); private: QHash _hash; }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d10cd1b17d..6d7ab5f96c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -472,6 +472,21 @@ void MyAvatar::loadData(QSettings* settings) { settings->endGroup(); } +void MyAvatar::sendKillAvatar() { + unsigned char packet[MAX_PACKET_SIZE]; + unsigned char* packetPosition = packet; + + packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_KILL_AVATAR); + + NodeList* nodeList = NodeList::getInstance(); + + QByteArray rfcUUID = nodeList->getOwnerUUID().toRfc4122(); + memcpy(packetPosition, rfcUUID.constData(), rfcUUID.size()); + packetPosition += rfcUUID.size(); + + nodeList->broadcastToNodes(packet, packetPosition - packet, &NODE_TYPE_AVATAR_MIXER, 1); +} + void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { // first orbit horizontally glm::quat orientation = getOrientation(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 894913f824..f9da7e3a82 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -25,7 +25,7 @@ enum AvatarHandState class MyAvatar : public Avatar { public: MyAvatar(Node* owningNode = NULL); - + void reset(); void simulate(float deltaTime, Transmitter* transmitter); void updateFromGyros(bool turnWithHead); @@ -62,6 +62,8 @@ public: void setDriveKeys(int key, float val) { _driveKeys[key] = val; }; bool getDriveKeys(int key) { return _driveKeys[key]; }; void jump() { _shouldJump = true; }; + + void sendKillAvatar(); // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index e821f105bd..320e0e9283 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -180,10 +180,6 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char processSTUNResponse(packetData, dataBytes); break; } - case PACKET_TYPE_KILL_NODE: { - processKillNode(packetData, dataBytes); - break; - } } } @@ -416,30 +412,13 @@ NodeHash::iterator NodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItem return _nodeHash.erase(nodeItemToKill); } -void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) { - unsigned char packet[MAX_PACKET_SIZE]; - unsigned char* packetPosition = packet; - - packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_KILL_NODE); - - QByteArray rfcUUID = _ownerUUID.toRfc4122(); - memcpy(packetPosition, rfcUUID.constData(), rfcUUID.size()); - packetPosition += rfcUUID.size(); - - broadcastToNodes(packet, packetPosition - packet, nodeTypes, numNodeTypes); -} - -void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) { - // skip the header - int numBytesPacketHeader = numBytesForPacketHeader(packetData); - packetData += numBytesPacketHeader; - dataBytes -= numBytesPacketHeader; - +void NodeList::processKillNode(const QByteArray& dataByteArray) { // read the node id - QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)packetData, NUM_BYTES_RFC4122_UUID)); + QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader(reinterpret_cast + (dataByteArray.data())), + NUM_BYTES_RFC4122_UUID)); - packetData += NUM_BYTES_RFC4122_UUID; - dataBytes -= NUM_BYTES_RFC4122_UUID; + // kill the node with this UUID, if it exists killNodeWithUUID(nodeUUID); } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 96ee78a9b0..d4ee5d1bf7 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -111,6 +111,8 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, size_t dataBytes); + + void processKillNode(const QByteArray& datagram); int updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes); @@ -141,7 +143,6 @@ private: void sendSTUNRequest(); void processSTUNResponse(unsigned char* packetData, size_t dataBytes); - void processKillNode(unsigned char* packetData, size_t dataBytes); NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); NodeHash _nodeHash; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 5d1c657d6b..84408ec630 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -18,7 +18,7 @@ const PACKET_TYPE PACKET_TYPE_STUN_RESPONSE = 1; const PACKET_TYPE PACKET_TYPE_DOMAIN = 'D'; const PACKET_TYPE PACKET_TYPE_PING = 'P'; const PACKET_TYPE PACKET_TYPE_PING_REPLY = 'R'; -const PACKET_TYPE PACKET_TYPE_KILL_NODE = 'K'; +const PACKET_TYPE PACKET_TYPE_KILL_AVATAR = 'K'; const PACKET_TYPE PACKET_TYPE_HEAD_DATA = 'H'; const PACKET_TYPE PACKET_TYPE_INJECT_AUDIO = 'I'; const PACKET_TYPE PACKET_TYPE_MIXED_AUDIO = 'A';