have avatar-mixer report avatar kills to all avatars

This commit is contained in:
Stephen Birarda 2014-01-23 12:47:27 -08:00
parent a9f1984676
commit 1f95d0c017
10 changed files with 78 additions and 36 deletions

View file

@ -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());

View file

@ -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);
};

View file

@ -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<char*>(incomingPacket), bytesReceived);
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
Q_ARG(const QByteArray&,
QByteArray(reinterpret_cast<char*>(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:

View file

@ -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<const unsigned char*>
(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();
}

View file

@ -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<QUuid, Avatar*> _hash;
};

View file

@ -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();

View file

@ -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; };

View file

@ -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
<const unsigned char*>(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);
}

View file

@ -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;

View file

@ -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';