change NodeList container to QHash with QSharedPointer

This commit is contained in:
Stephen Birarda 2014-01-13 17:09:21 -08:00
parent 0e25c85eef
commit 7d1a64ca8c
35 changed files with 355 additions and 737 deletions

View file

@ -182,15 +182,13 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
}
void AudioMixer::prepareMixForListeningNode(Node* node) {
NodeList* nodeList = NodeList::getInstance();
AvatarAudioRingBuffer* nodeRingBuffer = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer();
// zero out the client mix for this node
memset(_clientSamples, 0, sizeof(_clientSamples));
// loop through all other nodes that have sufficient audio to mix
for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) {
foreach(SharedNodePointer otherNode, NodeList::getInstance()->getNodeHash()) {
if (otherNode->getLinkedData()) {
AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData();
@ -200,7 +198,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) {
PositionalAudioRingBuffer* otherNodeBuffer = otherNodeClientData->getRingBuffers()[i];
if ((*otherNode != *node
|| otherNodeBuffer->shouldLoopbackForNode())
|| otherNodeBuffer->shouldLoopbackForNode())
&& otherNodeBuffer->willBeAddedToMix()) {
addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer);
}
@ -220,10 +218,10 @@ void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSock
NodeList* nodeList = NodeList::getInstance();
Node* matchingNode = nodeList->nodeWithUUID(nodeUUID);
SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID);
if (matchingNode) {
nodeList->updateNodeWithData(matchingNode, senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size());
nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size());
if (!matchingNode->getActiveSocket()) {
// we don't have an active socket for this node, but they're talking to us
@ -264,14 +262,14 @@ void AudioMixer::run() {
if (_isFinished) {
break;
}
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getLinkedData()) {
((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES);
}
}
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getType() == NODE_TYPE_AGENT && node->getActiveSocket() && node->getLinkedData()
&& ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) {
prepareMixForListeningNode(&(*node));
@ -284,12 +282,13 @@ void AudioMixer::run() {
}
// push forward the next output pointers for any audio buffers we used
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getLinkedData()) {
((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend();
}
}
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) {

View file

@ -67,7 +67,7 @@ void broadcastAvatarData() {
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT && node->getActiveSocket()) {
// reset packet pointers for this node
@ -76,7 +76,7 @@ void broadcastAvatarData() {
// this is an AGENT we have received head data from
// send back a packet with other active node data to this node
for (NodeList::iterator otherNode = nodeList->begin(); otherNode != nodeList->end(); otherNode++) {
foreach(SharedNodePointer otherNode, nodeList->getNodeHash()) {
if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) {
unsigned char* avatarDataEndpoint = addNodeToBroadcastPacket((unsigned char*)&avatarDataBuffer[0],
@ -109,13 +109,11 @@ void broadcastAvatarData() {
packetsSent++;
//printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength);
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) broadcastPacket, currentBufferPosition - broadcastPacket,
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
nodeList->getNodeSocket().writeDatagram((char*) broadcastPacket, currentBufferPosition - broadcastPacket,
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
}
}
}
void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
@ -128,11 +126,11 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc
NUM_BYTES_RFC4122_UUID));
// add or update the node in our list
Node* avatarNode = nodeList->nodeWithUUID(nodeUUID);
SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID);
if (avatarNode) {
// parse positional data from an node
nodeList->updateNodeWithData(avatarNode, senderSockAddr,
nodeList->updateNodeWithData(avatarNode.data(), senderSockAddr,
(unsigned char*) dataByteArray.data(), dataByteArray.size());
} else {
break;
@ -144,7 +142,7 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc
QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesForPacketHeader((unsigned char*) dataByteArray.data()),
NUM_BYTES_RFC4122_UUID));
// let everyone else know about the update
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getActiveSocket() && node->getUUID() != nodeUUID) {
nodeList->getNodeSocket().writeDatagram(dataByteArray,
node->getActiveSocket()->getAddress(),

View file

@ -77,7 +77,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
// Start the web server.
mg_start(&callbacks, NULL, options);
nodeList->addHook(this);
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
if (!_staticAssignmentFile.exists() || _voxelServerConfig) {
@ -171,10 +171,10 @@ void DomainServer::readAvailableDatagrams() {
nodeLocalAddress,
nodeUUID)))
{
Node* checkInNode = nodeList->addOrUpdateNode(nodeUUID,
nodeType,
nodePublicAddress,
nodeLocalAddress);
SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID,
nodeType,
nodePublicAddress,
nodeLocalAddress);
if (matchingStaticAssignment) {
// this was a newly added node with a matching static assignment
@ -201,7 +201,7 @@ void DomainServer::readAvailableDatagrams() {
if (numInterestTypes > 0) {
// if the node has sent no types of interest, assume they want nothing but their own ID back
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getUUID() != nodeUUID &&
memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) {
@ -318,9 +318,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
QJsonObject assignedNodesJSON;
// enumerate the NodeList to find the assigned nodes
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData()) {
// add the node using the UUID as the key
QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID());
@ -372,10 +370,10 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
// enumerate the NodeList to find the assigned nodes
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
// add the node using the UUID as the key
QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID());
nodesJSON[uuidString] = jsonObjectForNode(&(*node));
nodesJSON[uuidString] = jsonObjectForNode(node.data());
}
rootJSON["nodes"] = nodesJSON;
@ -410,14 +408,14 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
QUuid deleteUUID = QUuid(QString(ri->uri + strlen(URI_NODE) + sizeof('/')));
if (!deleteUUID.isNull()) {
Node *nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
if (nodeToKill) {
// start with a 200 response
mg_printf(connection, "%s", RESPONSE_200);
// we have a valid UUID and node - kill the node that has this assignment
NodeList::getInstance()->killNode(nodeToKill);
NodeList::getInstance()->killNodeWithUUID(deleteUUID);
// successfully processed request
return 1;
@ -494,10 +492,6 @@ void DomainServer::addReleasedAssignmentBackToQueue(Assignment* releasedAssignme
}
}
void DomainServer::nodeAdded(Node* node) {
}
void DomainServer::nodeKilled(Node* node) {
// if this node has linked data it was from an assignment
if (node->getLinkedData()) {
@ -741,7 +735,7 @@ bool DomainServer::checkInWithUUIDMatchesExistingNode(const HifiSockAddr& nodePu
const QUuid& checkInUUID) {
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getLinkedData()
&& nodePublicSocket == node->getPublicSocket()
&& nodeLocalSocket == node->getLocalSocket()
@ -773,7 +767,7 @@ void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() {
NodeList* nodeList = NodeList::getInstance();
// enumerate the nodes and check if there is one with an attached assignment with matching UUID
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getLinkedData()) {
Assignment* linkedAssignment = (Assignment*) node->getLinkedData();
if (linkedAssignment->getUUID() == _staticAssignments[i].getUUID()) {

View file

@ -22,7 +22,7 @@
const int MAX_STATIC_ASSIGNMENT_FILE_ASSIGNMENTS = 1000;
class DomainServer : public QCoreApplication, public NodeListHook {
class DomainServer : public QCoreApplication {
Q_OBJECT
public:
DomainServer(int argc, char* argv[]);
@ -31,10 +31,10 @@ public:
static void setDomainServerInstance(DomainServer* domainServer);
/// Called by NodeList to inform us that a node has been added.
void nodeAdded(Node* node);
public slots:
/// Called by NodeList to inform us that a node has been killed.
void nodeKilled(Node* node);
private:
static int civetwebRequestHandler(struct mg_connection *connection);
static void civetwebUploadHandler(struct mg_connection *connection, const char *path);

View file

@ -173,9 +173,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
connect(audioThread, SIGNAL(started()), &_audio, SLOT(start()));
audioThread->start();
nodeList->addHook(&_voxels);
nodeList->addHook(this);
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
nodeList->addDomainListener(this);
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
@ -263,8 +265,6 @@ Application::~Application() {
_audio.thread()->wait();
storeSizeAndPosition();
NodeList::getInstance()->removeHook(&_voxels);
NodeList::getInstance()->removeHook(this);
NodeList::getInstance()->removeDomainListener(this);
_sharedVoxelSystem.changeTree(new VoxelTree);
@ -1441,7 +1441,7 @@ void Application::terminate() {
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
// record the packet for stats-tracking
Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AVATARS).updateValue(dataBytes);
Node* avatarMixerNode = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
SharedNodePointer avatarMixerNode = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
if (avatarMixerNode) {
avatarMixerNode->recordBytesReceived(dataBytes);
}
@ -1458,7 +1458,7 @@ static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& da
dataBytes -= NUM_BYTES_RFC4122_UUID;
// make sure the node exists
Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
if (!node || !node->getLinkedData()) {
return NULL;
}
@ -1985,16 +1985,16 @@ void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, cons
Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection,
glm::vec3& eyePosition, QUuid& nodeUUID = DEFAULT_NODE_ID_REF) {
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar*)node->getLinkedData();
float distance;
if (avatar->findRayIntersection(mouseRayOrigin, mouseRayDirection, distance)) {
// rescale to compensate for head embiggening
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
_lookatIndicatorScale = avatar->getHead().getScale();
_lookatOtherPosition = avatar->getHead().getPosition();
nodeUUID = avatar->getOwningNode()->getUUID();
@ -2002,6 +2002,7 @@ Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, con
}
}
}
return NULL;
}
@ -2026,71 +2027,6 @@ void Application::renderLookatIndicator(glm::vec3 pointOfInterest) {
renderCircle(haloOrigin, INDICATOR_RADIUS, IDENTITY_UP, NUM_SEGMENTS);
}
void maybeBeginFollowIndicator(bool& began) {
if (!began) {
Application::getInstance()->getGlowEffect()->begin();
glLineWidth(5);
glBegin(GL_LINES);
began = true;
}
}
void Application::renderFollowIndicator() {
NodeList* nodeList = NodeList::getInstance();
// initialize lazily so that we don't enable the glow effect unnecessarily
bool began = false;
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) {
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar *) node->getLinkedData();
Avatar* leader = NULL;
if (!avatar->getLeaderUUID().isNull()) {
if (avatar->getLeaderUUID() == NodeList::getInstance()->getOwnerUUID()) {
leader = &_myAvatar;
} else {
for (NodeList::iterator it = nodeList->begin(); it != nodeList->end(); ++it) {
if(it->getUUID() == avatar->getLeaderUUID()
&& it->getType() == NODE_TYPE_AGENT) {
leader = (Avatar*) it->getLinkedData();
}
}
}
if (leader != NULL) {
maybeBeginFollowIndicator(began);
glColor3f(1.f, 0.f, 0.f);
glVertex3f((avatar->getHead().getPosition().x + avatar->getPosition().x) / 2.f,
(avatar->getHead().getPosition().y + avatar->getPosition().y) / 2.f,
(avatar->getHead().getPosition().z + avatar->getPosition().z) / 2.f);
glColor3f(0.f, 1.f, 0.f);
glVertex3f((leader->getHead().getPosition().x + leader->getPosition().x) / 2.f,
(leader->getHead().getPosition().y + leader->getPosition().y) / 2.f,
(leader->getHead().getPosition().z + leader->getPosition().z) / 2.f);
}
}
}
}
if (_myAvatar.getLeadingAvatar() != NULL) {
maybeBeginFollowIndicator(began);
glColor3f(1.f, 0.f, 0.f);
glVertex3f((_myAvatar.getHead().getPosition().x + _myAvatar.getPosition().x) / 2.f,
(_myAvatar.getHead().getPosition().y + _myAvatar.getPosition().y) / 2.f,
(_myAvatar.getHead().getPosition().z + _myAvatar.getPosition().z) / 2.f);
glColor3f(0.f, 1.f, 0.f);
glVertex3f((_myAvatar.getLeadingAvatar()->getHead().getPosition().x + _myAvatar.getLeadingAvatar()->getPosition().x) / 2.f,
(_myAvatar.getLeadingAvatar()->getHead().getPosition().y + _myAvatar.getLeadingAvatar()->getPosition().y) / 2.f,
(_myAvatar.getLeadingAvatar()->getHead().getPosition().z + _myAvatar.getLeadingAvatar()->getPosition().z) / 2.f);
}
if (began) {
glEnd();
_glowEffect.end();
}
}
void Application::renderHighlightVoxel(VoxelDetail voxel) {
glDisable(GL_LIGHTING);
glPushMatrix();
@ -2108,9 +2044,8 @@ void Application::renderHighlightVoxel(VoxelDetail voxel) {
void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm::vec3 mouseRayDirection) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
NodeList* nodeList = NodeList::getInstance();
for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
node->lock();
if (node->getLinkedData()) {
Avatar *avatar = (Avatar *)node->getLinkedData();
@ -2739,39 +2674,36 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node
unsigned char voxelQueryPacket[MAX_PACKET_SIZE];
NodeList* nodeList = NodeList::getInstance();
// Iterate all of the nodes, and get a count of how many voxel servers we have...
int totalServers = 0;
int inViewServers = 0;
int unknownJurisdictionServers = 0;
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
// only send to the NodeTypes that are serverType
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
totalServers++;
// get the server bounds for this server
QUuid nodeUUID = node->getUUID();
// if we haven't heard from this voxel server, go ahead and send it a query, so we
// can get the jurisdiction...
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
unknownJurisdictionServers++;
} else {
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inViewServers++;
}
@ -2804,18 +2736,20 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node
if (wantExtraDebugging && unknownJurisdictionServers > 0) {
qDebug("perServerPPS: %d perUnknownServer: %d\n", perServerPPS, perUnknownServer);
}
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
NodeList* nodeList = NodeList::getInstance();
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are serverType
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
// get the server bounds for this server
QUuid nodeUUID = node->getUUID();
bool inView = false;
bool unknownView = false;
// if we haven't heard from this voxel server, go ahead and send it a query, so we
// can get the jurisdiction...
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
@ -2825,15 +2759,15 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node
}
} else {
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
if (rootCode) {
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inView = true;
@ -2846,15 +2780,15 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node
}
}
}
if (inView) {
_voxelQuery.setMaxOctreePacketsPerSecond(perServerPPS);
} else if (unknownView) {
if (wantExtraDebugging) {
qDebug() << "no known jurisdiction for node " << *node << ", give it budget of "
<< perUnknownServer << " to send us jurisdiction.\n";
<< perUnknownServer << " to send us jurisdiction.\n";
}
// set the query's position/orientation to be degenerate in a manner that will get the scene quickly
// If there's only one server, then don't do this, and just let the normal voxel query pass through
// as expected... this way, we will actually get a valid scene if there is one to be seen
@ -2878,24 +2812,24 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node
}
// set up the packet for sending...
unsigned char* endOfVoxelQueryPacket = voxelQueryPacket;
// insert packet type/version and node UUID
endOfVoxelQueryPacket += populateTypeAndVersion(endOfVoxelQueryPacket, packetType);
QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122();
memcpy(endOfVoxelQueryPacket, ownerUUID.constData(), ownerUUID.size());
endOfVoxelQueryPacket += ownerUUID.size();
// encode the query data...
endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket);
int packetLength = endOfVoxelQueryPacket - voxelQueryPacket;
// make sure we still have an active socket
if (node->getActiveSocket()) {
nodeList->getNodeSocket().writeDatagram((char*) voxelQueryPacket, packetLength,
node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort());
node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort());
}
// Feed number of bytes to corresponding channel of the bandwidth meter
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
}
@ -3252,12 +3186,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
}
}
{
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... renderFollowIndicator...");
renderFollowIndicator();
}
// render transmitter pick ray, if non-empty
if (_transmitterPickStart != _transmitterPickEnd) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
@ -3384,12 +3312,12 @@ void Application::displayOverlay() {
glPointSize(1.0f);
char nodes[100];
NodeList* nodeList = NodeList::getInstance();
int totalAvatars = 0, totalServers = 0;
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
node->getType() == NODE_TYPE_AGENT ? totalAvatars++ : totalServers++;
}
sprintf(nodes, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
drawtext(_glWidget->width() - 150, 20, 0.10, 0, 1.0, 0, nodes, 1, 0, 0);
}
@ -3489,8 +3417,8 @@ void Application::displayStats() {
int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0;
NodeList* nodeList = NodeList::getInstance();
Node* audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
Node* avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0;
pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0;
@ -3499,7 +3427,8 @@ void Application::displayStats() {
// Now handle voxel servers, since there could be more than one, we average their ping times
unsigned long totalPingVoxel = 0;
int voxelServerCount = 0;
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
totalPingVoxel += node->getPingMs();
voxelServerCount++;
@ -3508,6 +3437,7 @@ void Application::displayStats() {
}
}
}
if (voxelServerCount) {
pingVoxel = totalPingVoxel/voxelServerCount;
}
@ -3524,7 +3454,7 @@ void Application::displayStats() {
sprintf(avatarStats, "Avatar: pos %.3f, %.3f, %.3f, vel %.1f, yaw = %.2f", avatarPos.x, avatarPos.y, avatarPos.z, glm::length(_myAvatar.getVelocity()), _myAvatar.getBodyYaw());
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarStats);
Node* avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
char avatarMixerStats[200];
if (avatarMixer) {
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
@ -3848,10 +3778,10 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) {
if (!selfAvatarOnly) {
// Render avatars of other nodes
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
node->lock();
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar *avatar = (Avatar *)node->getLinkedData();
if (!avatar->isInitialized()) {
@ -3860,7 +3790,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) {
avatar->render(false);
avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors));
}
node->unlock();
}
@ -4106,18 +4036,6 @@ void Application::eyedropperVoxelUnderCursor() {
}
}
void Application::toggleFollowMode() {
glm::vec3 mouseRayOrigin, mouseRayDirection;
_viewFrustum.computePickRay(_pieMenu.getX() / (float)_glWidget->width(),
_pieMenu.getY() / (float)_glWidget->height(),
mouseRayOrigin, mouseRayDirection);
glm::vec3 eyePositionIgnored;
QUuid nodeUUIDIgnored;
Avatar* leadingAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeUUIDIgnored);
_myAvatar.follow(leadingAvatar);
}
void Application::resetSensors() {
_headMouseX = _mouseX = _glWidget->width() / 2;
_headMouseY = _mouseY = _glWidget->height() / 2;
@ -4200,11 +4118,7 @@ void Application::domainChanged(QString domain) {
updateLocalOctreeCache();
}
void Application::nodeAdded(Node* node) {
}
void Application::nodeKilled(Node* node) {
void Application::nodeKilled(SharedNodePointer node) {
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
QUuid nodeUUID = node->getUUID();
// see if this is the first we've heard of this node...
@ -4284,7 +4198,7 @@ void Application::trackIncomingVoxelPacket(unsigned char* messageData, ssize_t m
const HifiSockAddr& senderSockAddr, bool wasStatsPacket) {
// Attempt to identify the sender from it's address.
Node* serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
if (serverNode) {
QUuid nodeUUID = serverNode->getUUID();
@ -4301,7 +4215,7 @@ void Application::trackIncomingVoxelPacket(unsigned char* messageData, ssize_t m
int Application::parseOctreeStats(unsigned char* messageData, ssize_t messageLength, const HifiSockAddr& senderSockAddr) {
// But, also identify the sender, and keep track of the contained jurisdiction root for this server
Node* server = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
SharedNodePointer server = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
// parse the incoming stats datas stick it in a temporary object for now, while we
// determine which server it belongs to

View file

@ -95,7 +95,7 @@ static const float NODE_KILLED_RED = 1.0f;
static const float NODE_KILLED_GREEN = 0.0f;
static const float NODE_KILLED_BLUE = 0.0f;
class Application : public QApplication, public NodeListHook, public PacketSenderNotify, public DomainChangeListener {
class Application : public QApplication, public PacketSenderNotify, public DomainChangeListener {
Q_OBJECT
friend class VoxelPacketProcessor;
@ -194,8 +194,7 @@ public:
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
virtual void packetSentNotification(ssize_t length);
virtual void domainChanged(QString domain);
@ -214,6 +213,8 @@ public:
void setIsHighlightVoxel(bool isHighlightVoxel) { _isHighlightVoxel = isHighlightVoxel; }
public slots:
void nodeKilled(SharedNodePointer node);
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
void exportVoxels();
void importVoxels();
@ -250,8 +251,6 @@ private slots:
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
void toggleFollowMode();
void closeMirrorView();
void restoreMirrorView();
void shrinkMirrorView();
@ -301,7 +300,6 @@ private:
bool isLookingAtMyAvatar(Avatar* avatar);
void renderLookatIndicator(glm::vec3 pointOfInterest);
void renderFollowIndicator();
void renderHighlightVoxel(VoxelDetail voxel);
void updateAvatar(float deltaTime);

View file

@ -365,9 +365,9 @@ void Audio::handleAudioInput() {
NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
NodeList* nodeList = NodeList::getInstance();
Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) {
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) {
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();

View file

@ -144,14 +144,14 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int
Application::getInstance()->getProfile()->setFaceModelURL(QUrl(valueList[i]));
} else {
// mesh URL for a UUID, find avatar in our list
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar *) node->getLinkedData();
if (avatar->getUUID() == userUUID) {
QMetaObject::invokeMethod(&avatar->getHead().getFaceModel(),
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
}
}
}
@ -163,14 +163,13 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int
Application::getInstance()->getProfile()->setSkeletonModelURL(QUrl(valueList[i]));
} else {
// skeleton URL for a UUID, find avatar in our list
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar *) node->getLinkedData();
if (avatar->getUUID() == userUUID) {
QMetaObject::invokeMethod(&avatar->getSkeletonModel(), "setURL",
Q_ARG(QUrl, QUrl(valueList[i])));
Q_ARG(QUrl, QUrl(valueList[i])));
}
}
}

View file

@ -26,10 +26,6 @@ MetavoxelSystem::MetavoxelSystem() :
_buffer(QOpenGLBuffer::VertexBuffer) {
}
MetavoxelSystem::~MetavoxelSystem() {
NodeList::getInstance()->removeHook(this);
}
void MetavoxelSystem::init() {
if (!_program.isLinked()) {
switchToResourcesParentIfRequired();
@ -39,7 +35,10 @@ void MetavoxelSystem::init() {
_pointScaleLocation = _program.uniformLocation("pointScale");
}
NodeList::getInstance()->addHook(this);
NodeList* nodeList = NodeList::getInstance();
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
AttributeRegistry::getInstance()->configureScriptEngine(&_scriptEngine);
@ -117,14 +116,14 @@ void MetavoxelSystem::render() {
_program.release();
}
void MetavoxelSystem::nodeAdded(Node* node) {
void MetavoxelSystem::nodeAdded(SharedNodePointer node) {
if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) {
QMetaObject::invokeMethod(this, "addClient", Q_ARG(const QUuid&, node->getUUID()),
Q_ARG(const HifiSockAddr&, node->getLocalSocket()));
}
}
void MetavoxelSystem::nodeKilled(Node* node) {
void MetavoxelSystem::nodeKilled(SharedNodePointer node) {
if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) {
QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID()));
}

View file

@ -26,13 +26,11 @@
class MetavoxelClient;
/// Renders a metavoxel tree.
class MetavoxelSystem : public QObject, public NodeListHook {
class MetavoxelSystem : public QObject {
Q_OBJECT
public:
MetavoxelSystem();
~MetavoxelSystem();
void init();
@ -41,9 +39,9 @@ public:
void simulate(float deltaTime);
void render();
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
public slots:
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node);
private:
Q_INVOKABLE void addClient(const QUuid& uuid, const HifiSockAddr& address);

View file

@ -57,12 +57,13 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, uns
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
app->trackIncomingVoxelPacket(packetData, messageLength, senderSockAddr, wasStatsPacket);
Node* serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
if (serverNode && serverNode->getActiveSocket() && *serverNode->getActiveSocket() == senderSockAddr) {
switch(packetData[0]) {
case PACKET_TYPE_PARTICLE_DATA: {
app->_particles.processDatagram(QByteArray((char*) packetData, messageLength), senderSockAddr, serverNode);
app->_particles.processDatagram(QByteArray((char*) packetData, messageLength),
senderSockAddr, serverNode.data());
} break;
case PACKET_TYPE_ENVIRONMENT_DATA: {

View file

@ -1604,13 +1604,13 @@ void VoxelSystem::falseColorizeBySource() {
};
// create a bunch of colors we'll use during colorization
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
uint16_t nodeID = VoxelTreeElement::getSourceNodeUUIDKey(node->getUUID());
int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS;
args.colors[nodeID] = groupColors[groupColor];
if (groupColors[groupColor].red > 0) {
groupColors[groupColor].red = ((groupColors[groupColor].red - MIN_COLOR)/2) + MIN_COLOR;
}
@ -1620,7 +1620,7 @@ void VoxelSystem::falseColorizeBySource() {
if (groupColors[groupColor].blue > 0) {
groupColors[groupColor].blue = ((groupColors[groupColor].blue - MIN_COLOR)/2) + MIN_COLOR;
}
voxelServerCount++;
}
}
@ -2683,7 +2683,7 @@ void VoxelSystem::falseColorizeOccludedV2() {
setupNewVoxelsForDrawing();
}
void VoxelSystem::nodeAdded(Node* node) {
void VoxelSystem::nodeAdded(SharedNodePointer node) {
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
qDebug("VoxelSystem... voxel server %s added...\n", node->getUUID().toString().toLocal8Bit().constData());
_voxelServerCount++;
@ -2704,7 +2704,7 @@ bool VoxelSystem::killSourceVoxelsOperation(OctreeElement* element, void* extraD
return true;
}
void VoxelSystem::nodeKilled(Node* node) {
void VoxelSystem::nodeKilled(SharedNodePointer node) {
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
_voxelServerCount--;
QUuid nodeUUID = node->getUUID();

View file

@ -37,8 +37,7 @@ struct VoxelShaderVBOData
};
class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook,
public NodeListHook {
class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook {
Q_OBJECT
friend class VoxelHideShowThread;
@ -112,8 +111,6 @@ public:
virtual void elementDeleted(OctreeElement* element);
virtual void elementUpdated(OctreeElement* element);
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
bool treeIsBusy() const { return _treeIsBusy; }
@ -124,6 +121,9 @@ signals:
void importProgress(int progress);
public slots:
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node);
void collectStatsForTreesAndVBOs();
// Methods that recurse tree

View file

@ -95,7 +95,6 @@ Avatar::Avatar(Node* owningNode) :
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
_mouseRayDirection(0.0f, 0.0f, 0.0f),
_isCollisionsOn(true),
_leadingAvatar(NULL),
_moving(false),
_initialized(false),
_handHoldingPosition(0.0f, 0.0f, 0.0f),
@ -146,27 +145,7 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
return computeRotationFromBodyToWorldUp() * getOrientation();
}
void Avatar::follow(Avatar* leadingAvatar) {
const float MAX_STRING_LENGTH = 2;
_leadingAvatar = leadingAvatar;
if (_leadingAvatar != NULL) {
_leaderUUID = leadingAvatar->getOwningNode()->getUUID();
_stringLength = glm::length(_position - _leadingAvatar->getPosition()) / _scale;
if (_stringLength > MAX_STRING_LENGTH) {
_stringLength = MAX_STRING_LENGTH;
}
} else {
_leaderUUID = QUuid();
}
}
void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) {
follow(NULL);
}
if (_scale != _newScale) {
setScale(_newScale);
}

View file

@ -135,7 +135,6 @@ public:
void init();
void simulate(float deltaTime, Transmitter* transmitter);
void follow(Avatar* leadingAvatar);
void render(bool forceRenderHead);
//setters
@ -217,7 +216,6 @@ protected:
glm::vec3 _mouseRayOrigin;
glm::vec3 _mouseRayDirection;
bool _isCollisionsOn;
Avatar* _leadingAvatar;
float _stringLength;
bool _moving; ///< set when position is changing

View file

@ -368,8 +368,7 @@ void Hand::updateCollisions() {
glm::vec3 totalPenetration;
// check other avatars
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
Avatar* otherAvatar = (Avatar*)node->getLinkedData();
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
@ -388,21 +387,21 @@ void Hand::updateCollisions() {
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
palm.setIsCollidingWithPalm(true);
if (!wasColliding) {
const float PALM_COLLIDE_VOLUME = 1.f;
const float PALM_COLLIDE_FREQUENCY = 1000.f;
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
PALM_COLLIDE_FREQUENCY,
PALM_COLLIDE_DURATION_MAX,
PALM_COLLIDE_DECAY_PER_SAMPLE);
// If the other person's palm is in motion, move mine downward to show I was hit
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
const float PALM_COLLIDE_VOLUME = 1.f;
const float PALM_COLLIDE_FREQUENCY = 1000.f;
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
PALM_COLLIDE_FREQUENCY,
PALM_COLLIDE_DURATION_MAX,
PALM_COLLIDE_DECAY_PER_SAMPLE);
// If the other person's palm is in motion, move mine downward to show I was hit
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
// add slapback here
}
}
}
}

View file

@ -87,15 +87,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
_elapsedTimeMoving += deltaTime;
}
if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) {
follow(NULL);
}
// Ajust, scale, position and lookAt position when following an other avatar
if (_leadingAvatar && _newScale != _leadingAvatar->getScale()) {
_newScale = _leadingAvatar->getScale();
}
if (_scale != _newScale) {
float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale;
setScale(scale);
@ -327,9 +318,7 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) {
estimatedRotation = webcam->getEstimatedRotation();
} else {
if (!_leadingAvatar) {
_head.setPitch(_head.getMousePitch());
}
_head.setPitch(_head.getMousePitch());
_head.getVideoFace().clearFrame();
// restore rotation, lean to neutral positions
@ -634,47 +623,6 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
_shouldJump = false;
}
// Add thrusts from leading avatar
const float FOLLOWING_RATE = 0.02f;
const float MIN_YAW = 5.0f;
const float MIN_PITCH = 1.0f;
const float PITCH_RATE = 0.1f;
const float MIN_YAW_BEFORE_PITCH = 30.0f;
if (_leadingAvatar != NULL) {
glm::vec3 toTarget = _leadingAvatar->getPosition() - _position;
if (glm::length(_position - _leadingAvatar->getPosition()) > _scale * _stringLength) {
_position += toTarget * FOLLOWING_RATE;
} else {
toTarget = _leadingAvatar->getHead().getLookAtPosition() - _head.getPosition();
}
toTarget = glm::vec3(glm::dot(right, toTarget),
glm::dot(up , toTarget),
glm::dot(front, toTarget));
float yawAngle = angleBetween(-IDENTITY_FRONT, glm::vec3(toTarget.x, 0.f, toTarget.z));
if (glm::abs(yawAngle) > MIN_YAW){
if (IDENTITY_RIGHT.x * toTarget.x + IDENTITY_RIGHT.y * toTarget.y + IDENTITY_RIGHT.z * toTarget.z > 0) {
_bodyYawDelta -= yawAngle;
} else {
_bodyYawDelta += yawAngle;
}
}
float pitchAngle = glm::abs(90.0f - angleBetween(IDENTITY_UP, toTarget));
if (glm::abs(pitchAngle) > MIN_PITCH && yawAngle < MIN_YAW_BEFORE_PITCH){
if (IDENTITY_UP.x * toTarget.x + IDENTITY_UP.y * toTarget.y + IDENTITY_UP.z * toTarget.z > 0) {
_head.setMousePitch(_head.getMousePitch() + PITCH_RATE * pitchAngle);
} else {
_head.setMousePitch(_head.getMousePitch() - PITCH_RATE * pitchAngle);
}
_head.setPitch(_head.getMousePitch());
}
}
// Add thrusts from Transmitter
if (transmitter) {
transmitter->checkForLostTransmitter();
@ -873,15 +821,7 @@ void MyAvatar::updateAvatarCollisions(float deltaTime) {
// Reset detector for nearest avatar
_distanceToNearestAvatar = std::numeric_limits<float>::max();
// loop through all the other avatars for potential interactions...
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
//Avatar *otherAvatar = (Avatar *)node->getLinkedData();
//
// Placeholder: Add code here when we want to add Avatar<->Avatar collision stuff
}
}
// loop through all the other avatars for potential interactions
}
class SortedAvatar {
@ -902,10 +842,10 @@ void MyAvatar::updateChatCircle(float deltaTime) {
// find all circle-enabled members and sort by distance
QVector<SortedAvatar> sortedAvatars;
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
SortedAvatar sortedAvatar;
SortedAvatar sortedAvatar;
sortedAvatar.avatar = (Avatar*)node->getLinkedData();
if (!sortedAvatar.avatar->isChatCirclingEnabled()) {
continue;
@ -914,6 +854,7 @@ void MyAvatar::updateChatCircle(float deltaTime) {
sortedAvatars.append(sortedAvatar);
}
}
qSort(sortedAvatars.begin(), sortedAvatars.end());
// compute the accumulated centers

View file

@ -51,7 +51,6 @@ public:
float getAbsoluteHeadYaw() const;
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
Avatar* getLeadingAvatar() const { return _leadingAvatar; }
glm::vec3 getGravity() const { return _gravity; }
glm::vec3 getUprightHeadPosition() const;
glm::vec3 getEyeLevelPosition() const;

View file

@ -241,9 +241,10 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
NodeToJurisdictionMap& serverJurisdictions) {
QLocale locale(QLocale::English);
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER
if (node->getType() == serverType) {
serverCount++;
@ -261,7 +262,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
std::stringstream serverDetails("");
std::stringstream extraDetails("");
std::stringstream linkDetails("");
if (nodeList->getNodeActiveSocketOrPing(&(*node))) {
serverDetails << "active ";
} else {
@ -270,29 +271,29 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
QUuid nodeUUID = node->getUUID();
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// missing at least one jurisdiction
if (serverJurisdictions.find(nodeUUID) == serverJurisdictions.end()) {
serverDetails << " unknown jurisdiction ";
} else {
const JurisdictionMap& map = serverJurisdictions[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode();
if (rootCode) {
QString rootCodeHex = octalCodeToHexString(rootCode);
VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, rootDetails);
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
serverBounds.scale(TREE_SCALE);
serverDetails << " jurisdiction: "
<< rootCodeHex.toLocal8Bit().constData()
<< " ["
<< rootDetails.x << ", "
<< rootDetails.y << ", "
<< rootDetails.z << ": "
<< rootDetails.s << "] ";
serverDetails << " jurisdiction: "
<< rootCodeHex.toLocal8Bit().constData()
<< " ["
<< rootDetails.x << ", "
<< rootDetails.y << ", "
<< rootDetails.z << ": "
<< rootDetails.s << "] ";
} else {
serverDetails << " jurisdiction has no rootCode";
} // root code
@ -304,7 +305,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getOcteeSceneStats();
if (sceneStats->find(nodeUUID) != sceneStats->end()) {
VoxelSceneStats& stats = sceneStats->at(nodeUUID);
switch (_extraServerDetails[serverCount-1]) {
case MOST: {
extraDetails << "<br/>" ;
@ -312,14 +313,14 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
const unsigned long USECS_PER_MSEC = 1000;
float lastFullEncode = stats.getLastFullTotalEncodeTime() / USECS_PER_MSEC;
float lastFullSend = stats.getLastFullElapsedTime() / USECS_PER_MSEC;
QString lastFullEncodeString = locale.toString(lastFullEncode);
QString lastFullSendString = locale.toString(lastFullSend);
extraDetails << "<br/>" << "Last Full Scene... " <<
"Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " <<
"Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms ";
extraDetails << "<br/>" << "Last Full Scene... " <<
"Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " <<
"Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms ";
for (int i = 0; i < VoxelSceneStats::ITEM_COUNT; i++) {
VoxelSceneStats::Item item = (VoxelSceneStats::Item)(i);
VoxelSceneStats::ItemInfo& itemInfo = stats.getItemInfo(item);
@ -330,44 +331,44 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
QString totalString = locale.toString((uint)stats.getTotalElements());
QString internalString = locale.toString((uint)stats.getTotalInternal());
QString leavesString = locale.toString((uint)stats.getTotalLeaves());
serverDetails << "<br/>" << "Node UUID: " <<
nodeUUID.toString().toLocal8Bit().constData() << " ";
nodeUUID.toString().toLocal8Bit().constData() << " ";
serverDetails << "<br/>" << "Voxels: " <<
totalString.toLocal8Bit().constData() << " total " <<
internalString.toLocal8Bit().constData() << " internal " <<
leavesString.toLocal8Bit().constData() << " leaves ";
totalString.toLocal8Bit().constData() << " total " <<
internalString.toLocal8Bit().constData() << " internal " <<
leavesString.toLocal8Bit().constData() << " leaves ";
QString incomingPacketsString = locale.toString((uint)stats.getIncomingPackets());
QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes());
QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes());
QString incomingOutOfOrderString = locale.toString((uint)stats.getIncomingOutOfOrder());
QString incomingLikelyLostString = locale.toString((uint)stats.getIncomingLikelyLost());
int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC;
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
QString incomingPingTimeString = locale.toString(node->getPingMs());
QString incomingClockSkewString = locale.toString(clockSkewInMS);
serverDetails << "<br/>" << "Incoming Packets: " <<
incomingPacketsString.toLocal8Bit().constData() <<
" Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() <<
" Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData();
incomingPacketsString.toLocal8Bit().constData() <<
" Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() <<
" Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData();
serverDetails << "<br/>" <<
" Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs";
serverDetails << "<br/>" <<
" Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs";
serverDetails << "<br/>" <<
" Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs";
" Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs";
serverDetails << "<br/>" <<
" Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs";
serverDetails << "<br/>" <<
" Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs";
serverDetails << "<br/>" << "Incoming" <<
" Bytes: " << incomingBytesString.toLocal8Bit().constData() <<
" Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData();
" Bytes: " << incomingBytesString.toLocal8Bit().constData() <<
" Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData();
serverDetails << extraDetails.str();
if (_extraServerDetails[serverCount-1] == MORE) {
linkDetails << " " << " [<a href='most-" << serverCount << "'>most...</a>]";
@ -376,7 +377,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
linkDetails << " " << " [<a href='more-" << serverCount << "'>less...</a>]";
linkDetails << " " << " [<a href='less-" << serverCount << "'>least...</a>]";
}
} break;
case LESS: {
// nothing
@ -391,7 +392,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serve
serverDetails << linkDetails.str();
_labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str());
} // is VOXEL_SERVER
} // Node Loop
}
}
void VoxelStatsDialog::reject() {

View file

@ -103,9 +103,9 @@ void AudioInjector::injectAudio() {
// grab our audio mixer from the NodeList, if it exists
Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) {
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) {
// send off this audio packet
nodeList->getNodeSocket().writeDatagram((char*) injectedAudioPacket,
(currentPacketPosition - injectedAudioPacket) + bytesToCopy,

View file

@ -30,7 +30,6 @@ AvatarData::AvatarData(Node* owningNode) :
_bodyPitch(0.0),
_bodyRoll(0.0),
_newScale(1.0f),
_leaderUUID(),
_handState(0),
_keyState(NO_KEY_DOWN),
_isChatCirclingEnabled(false),
@ -77,10 +76,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
// Body scale
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale);
// Follow mode info
memcpy(destinationBuffer, _leaderUUID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID);
destinationBuffer += NUM_BYTES_RFC4122_UUID;
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw);
@ -200,10 +195,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
// Body scale
sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale);
// Follow mode info
_leaderUUID = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID));
sourceBuffer += NUM_BYTES_RFC4122_UUID;
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
float headYaw, headPitch, headRoll;
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw);

View file

@ -100,8 +100,6 @@ public:
QString getQStringChatMessage() { return QString(_chatMessage.data()); }
bool isChatCirclingEnabled() const { return _isChatCirclingEnabled; }
const QUuid& getLeaderUUID() const { return _leaderUUID; }
const HeadData* getHeadData() const { return _headData; }
const HandData* getHandData() const { return _handData; }
@ -134,9 +132,6 @@ protected:
// Body scale
float _newScale;
// Following mode infos
QUuid _leaderUUID;
// Hand state (are we grabbing something or not)
char _handState;

View file

@ -57,7 +57,7 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket);
_receivedPacketCount++;
Node* senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
SharedNodePointer senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
unsigned short int sequence = (*((unsigned short int*)(packetData + numBytesPacketHeader)));
uint64_t sentAt = (*((uint64_t*)(packetData + numBytesPacketHeader + sizeof(sequence))));
@ -87,7 +87,9 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
_myServer->getOctree()->lockForWrite();
uint64_t startProcess = usecTimestampNow();
int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType,
packetData, packetLength, editData, maxSize, senderNode);
packetData,
packetLength,
editData, maxSize, senderNode.data());
_myServer->getOctree()->unlock();
uint64_t endProcess = usecTimestampNow();

View file

@ -30,7 +30,7 @@ bool OctreeSendThread::process() {
// don't do any send processing until the initial load of the octree is complete...
if (_myServer->isInitialLoadComplete()) {
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
if (node) {
// make sure the node list doesn't kill our node while we're using it
@ -48,7 +48,7 @@ bool OctreeSendThread::process() {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
}
packetsSent = packetDistributor(node, nodeData, viewFrustumChanged);
packetsSent = packetDistributor(node.data(), nodeData, viewFrustumChanged);
}
node->unlock(); // we're done with this node for now.

View file

@ -27,11 +27,7 @@ void OctreeServer::attachQueryNodeToNode(Node* newNode) {
}
}
void OctreeServer::nodeAdded(Node* node) {
// do nothing
}
void OctreeServer::nodeKilled(Node* node) {
void OctreeServer::nodeKilled(SharedNodePointer node) {
// Use this to cleanup our node
if (node->getType() == NODE_TYPE_AGENT) {
OctreeQueryNode* nodeData = (OctreeQueryNode*)node->getLinkedData();
@ -90,9 +86,6 @@ OctreeServer::~OctreeServer() {
_persistThread->terminate();
delete _persistThread;
}
// tell our NodeList we're done with notifications
NodeList::getInstance()->removeHook(this);
delete _jurisdiction;
_jurisdiction = NULL;
@ -524,10 +517,10 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo
QUuid nodeUUID = QUuid::fromRfc4122(dataByteArray.mid(numBytesPacketHeader,
NUM_BYTES_RFC4122_UUID));
Node* node = nodeList->nodeWithUUID(nodeUUID);
SharedNodePointer node = nodeList->nodeWithUUID(nodeUUID);
if (node) {
nodeList->updateNodeWithData(node, senderSockAddr, (unsigned char *) dataByteArray.data(),
nodeList->updateNodeWithData(node.data(), senderSockAddr, (unsigned char *) dataByteArray.data(),
dataByteArray.size());
if (!node->getActiveSocket()) {
// we don't have an active socket for this node, but they're talking to us
@ -612,7 +605,7 @@ void OctreeServer::run() {
setvbuf(stdout, NULL, _IOLBF, 0);
// tell our NodeList about our desire to get notifications
nodeList->addHook(this);
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
nodeList->linkedDataCreateCallback = &OctreeServer::attachQueryNodeToNode;
srand((unsigned)time(0));

View file

@ -23,7 +23,7 @@
#include "OctreeInboundPacketProcessor.h"
/// Handles assignments of type OctreeServer - sending octrees to various clients.
class OctreeServer : public ThreadedAssignment, public NodeListHook {
class OctreeServer : public ThreadedAssignment {
public:
OctreeServer(const unsigned char* dataBuffer, int numBytes);
~OctreeServer();
@ -60,15 +60,13 @@ public:
virtual int sendSpecialPacket(Node* node) { return 0; }
static void attachQueryNodeToNode(Node* newNode);
// NodeListHook
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
public slots:
/// runs the voxel server assignment
void run();
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
void nodeKilled(SharedNodePointer node);
protected:
int _argc;

View file

@ -15,29 +15,20 @@
#include <PacketHeaders.h>
#include "JurisdictionListener.h"
JurisdictionListener::JurisdictionListener(NODE_TYPE type, PacketSenderNotify* notify) :
PacketSender(notify, JurisdictionListener::DEFAULT_PACKETS_PER_SECOND)
{
_nodeType = type;
ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to
NodeList* nodeList = NodeList::getInstance();
nodeList->addHook(this);
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
//qDebug("JurisdictionListener::JurisdictionListener(NODE_TYPE type=%c)\n", type);
}
JurisdictionListener::~JurisdictionListener() {
NodeList* nodeList = NodeList::getInstance();
nodeList->removeHook(this);
}
void JurisdictionListener::nodeAdded(Node* node) {
// nothing to do. But need to implement it.
}
void JurisdictionListener::nodeKilled(Node* node) {
void JurisdictionListener::nodeKilled(SharedNodePointer node) {
if (_jurisdictions.find(node->getUUID()) != _jurisdictions.end()) {
_jurisdictions.erase(_jurisdictions.find(node->getUUID()));
}
@ -52,8 +43,9 @@ bool JurisdictionListener::queueJurisdictionRequest() {
int nodeCount = 0;
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
if (nodeList->getNodeActiveSocketOrPing(&(*node)) &&
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
if (nodeList->getNodeActiveSocketOrPing(&(*node)) &&
node->getType() == getNodeType()) {
const HifiSockAddr* nodeAddress = node->getActiveSocket();
PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
@ -73,7 +65,7 @@ bool JurisdictionListener::queueJurisdictionRequest() {
void JurisdictionListener::processPacket(const HifiSockAddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
if (packetData[0] == PACKET_TYPE_JURISDICTION) {
Node* node = NodeList::getInstance()->nodeWithAddress(senderAddress);
SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress);
if (node) {
QUuid nodeUUID = node->getUUID();
JurisdictionMap map;

View file

@ -15,32 +15,32 @@
#include <PacketSender.h>
#include <ReceivedPacketProcessor.h>
#include "JurisdictionMap.h"
/// Sends out PACKET_TYPE_JURISDICTION_REQUEST packets to all voxel servers and then listens for and processes
/// the PACKET_TYPE_JURISDICTION packets it receives in order to maintain an accurate state of all jurisidictions
/// within the domain. As with other ReceivedPacketProcessor classes the user is responsible for reading inbound packets
/// and adding them to the processing queue by calling queueReceivedPacket()
class JurisdictionListener : public NodeListHook, public PacketSender, public ReceivedPacketProcessor {
class JurisdictionListener : public PacketSender, public ReceivedPacketProcessor {
public:
static const int DEFAULT_PACKETS_PER_SECOND = 1;
static const int NO_SERVER_CHECK_RATE = 60; // if no servers yet detected, keep checking at 60fps
JurisdictionListener(NODE_TYPE type = NODE_TYPE_VOXEL_SERVER, PacketSenderNotify* notify = NULL);
~JurisdictionListener();
virtual bool process();
NodeToJurisdictionMap* getJurisdictions() { return &_jurisdictions; };
/// Called by NodeList to inform us that a node has been added.
void nodeAdded(Node* node);
/// Called by NodeList to inform us that a node has been killed.
void nodeKilled(Node* node);
NODE_TYPE getNodeType() const { return _nodeType; }
void setNodeType(NODE_TYPE type) { _nodeType = type; }
public slots:
/// Called by NodeList to inform us that a node has been killed.
void nodeKilled(SharedNodePointer node);
protected:
/// Callback for processing of received packets. Will process any queued PACKET_TYPE_JURISDICTION and update the
/// jurisdiction map member variable

View file

@ -32,7 +32,7 @@ JurisdictionSender::~JurisdictionSender() {
void JurisdictionSender::processPacket(const HifiSockAddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
if (packetData[0] == PACKET_TYPE_JURISDICTION_REQUEST) {
Node* node = NodeList::getInstance()->nodeWithAddress(senderAddress);
SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress);
if (node) {
QUuid nodeUUID = node->getUUID();
lockRequestingNodes();
@ -64,7 +64,7 @@ bool JurisdictionSender::process() {
QUuid nodeUUID = _nodesRequestingJurisdictions.front();
_nodesRequestingJurisdictions.pop();
Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
if (node->getActiveSocket() != NULL) {
const HifiSockAddr* nodeAddress = node->getActiveSocket();

View file

@ -21,6 +21,7 @@
/// to requesting parties. As with other ReceivedPacketProcessor classes the user is responsible for reading inbound packets
/// and adding them to the processing queue by calling queueReceivedPacket()
class JurisdictionSender : public PacketSender, public ReceivedPacketProcessor {
Q_OBJECT
public:
static const int DEFAULT_PACKETS_PER_SECOND = 1;

View file

@ -57,14 +57,15 @@ bool OctreeEditPacketSender::serversExist() const {
bool hasServers = false;
bool atLeastOnJurisdictionMissing = false; // assume the best
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType()) {
if (nodeList->getNodeActiveSocketOrPing(&(*node))) {
QUuid nodeUUID = node->getUUID();
// If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server
if (_serverJurisdictions) {
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
// missing at least one jurisdiction
if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) {
atLeastOnJurisdictionMissing = true;
@ -77,6 +78,7 @@ bool OctreeEditPacketSender::serversExist() const {
break; // no point in looking further...
}
}
return (hasServers && !atLeastOnJurisdictionMissing);
}
@ -84,7 +86,8 @@ bool OctreeEditPacketSender::serversExist() const {
// a known nodeID.
void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) {
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType() &&
((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) {
@ -100,11 +103,11 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
uint64_t createdAt = (*((uint64_t*)(buffer + numBytesPacketHeader + sizeof(sequence))));
uint64_t queuedAt = usecTimestampNow();
uint64_t transitTime = queuedAt - createdAt;
qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] <<
" - command to node bytes=" << length <<
" sequence=" << sequence <<
" transitTimeSoFar=" << transitTime << " usecs\n";
}
qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] <<
" - command to node bytes=" << length <<
" sequence=" << sequence <<
" transitTimeSoFar=" << transitTime << " usecs\n";
}
}
}
}
@ -166,13 +169,13 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t l
// But we can't really do that with a packed message, since each edit message could be destined
// for a different server... So we need to actually manage multiple queued packets... one
// for each server
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType()
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
QUuid nodeUUID = node->getUUID();
bool isMyJurisdiction = true;
// we need to get the jurisdiction for this
// we need to get the jurisdiction for this
// here we need to get the "pending packet" for this server
const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID];
isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN);
@ -212,15 +215,15 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c
// But we can't really do that with a packed message, since each edit message could be destined
// for a different server... So we need to actually manage multiple queued packets... one
// for each server
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType()
if (node->getActiveSocket() != NULL && node->getType() == getMyNodeType()) {
QUuid nodeUUID = node->getUUID();
bool isMyJurisdiction = true;
if (_serverJurisdictions) {
// we need to get the jurisdiction for this
// we need to get the jurisdiction for this
// here we need to get the "pending packet" for this server
if ((*_serverJurisdictions).find(nodeUUID) != (*_serverJurisdictions).end()) {
const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID];
@ -232,19 +235,19 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c
if (isMyJurisdiction) {
EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID];
packetBuffer._nodeUUID = nodeUUID;
// If we're switching type, then we send the last one and start over
if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) ||
if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) ||
(packetBuffer._currentSize + length >= _maxPacketSize)) {
releaseQueuedPacket(packetBuffer);
initializePacket(packetBuffer, type);
}
// If the buffer is empty and not correctly initialized for our type...
if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) {
initializePacket(packetBuffer, type);
}
// This is really the first time we know which server/node this particular edit message
// is going to, so we couldn't adjust for clock skew till now. But here's our chance.
// We call this virtual function that allows our specific type of EditPacketSender to
@ -252,7 +255,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PACKET_TYPE type, unsigned c
if (node->getClockSkewUsec() != 0) {
adjustEditPacketForClockSkew(codeColorBuffer, length, node->getClockSkewUsec());
}
memcpy(&packetBuffer._currentBuffer[packetBuffer._currentSize], codeColorBuffer, length);
packetBuffer._currentSize += length;
}

View file

@ -187,22 +187,22 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
}
// loop through all the other avatars for potential interactions...
NodeList* nodeList = NodeList::getInstance();
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
foreach(SharedNodePointer node, NodeList::getInstance()->getNodeHash()) {
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
AvatarData* avatar = static_cast<AvatarData*>(node->getLinkedData());
//printf("updateCollisionWithAvatars()...avatar=%p\n", avatar);
// check hands...
const HandData* handData = avatar->getHandData();
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
// apply a hard collision when ball collides with hand
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
if (collidingPalm) {
@ -210,9 +210,9 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
addedVelocity = palmVelocity;
}
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);

View file

@ -52,10 +52,9 @@ NodeList* NodeList::getInstance() {
}
NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
_nodeHash(),
_domainHostname(DEFAULT_DOMAIN_HOSTNAME),
_domainSockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
_nodeBuckets(),
_numNodes(0),
_nodeSocket(),
_ownerType(newOwnerType),
_nodeTypesOfInterest(NULL),
@ -108,10 +107,10 @@ void NodeList::setDomainHostname(const QString& domainHostname) {
}
void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData) {
for(NodeList::iterator node = begin(); node != end(); node++) {
foreach(SharedNodePointer node, _nodeHash) {
if (node->getPublicSocket() == nodeAddress ||
node->getLocalSocket() == nodeAddress) {
unsigned char* dataAt = packetData + numBytesForPacketHeader(packetData);
uint64_t ourOriginalTime = *(uint64_t*)(dataAt);
dataAt += sizeof(ourOriginalTime);
@ -129,15 +128,15 @@ void NodeList::timePingReply(const HifiSockAddr& nodeAddress, unsigned char *pac
node->setClockSkewUsec(clockSkew);
const bool wantDebug = false;
if (wantDebug) {
if (wantDebug) {
qDebug() << "PING_REPLY from node " << *node << "\n" <<
" now: " << now << "\n" <<
" ourTime: " << ourOriginalTime << "\n" <<
" pingTime: " << pingTime << "\n" <<
" oneWayFlightTime: " << oneWayFlightTime << "\n" <<
" othersReplyTime: " << othersReplyTime << "\n" <<
" othersExprectedReply: " << othersExprectedReply << "\n" <<
" clockSkew: " << clockSkew << "\n";
" now: " << now << "\n" <<
" ourTime: " << ourOriginalTime << "\n" <<
" pingTime: " << pingTime << "\n" <<
" oneWayFlightTime: " << oneWayFlightTime << "\n" <<
" othersReplyTime: " << othersReplyTime << "\n" <<
" othersExprectedReply: " << othersExprectedReply << "\n" <<
" clockSkew: " << clockSkew << "\n";
}
break;
}
@ -184,10 +183,9 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char
}
void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned char *packetData, int numTotalBytes) {
SharedNodePointer bulkSendNode = nodeWithAddress(senderAddress);
// find the avatar mixer in our node list and update the lastRecvTime from it
Node* bulkSendNode = nodeWithAddress(senderAddress);
if (bulkSendNode) {
bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
@ -209,14 +207,14 @@ void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned c
numTotalBytes - (currentPosition - startPosition));
QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)currentPosition, NUM_BYTES_RFC4122_UUID));
Node* matchingNode = nodeWithUUID(nodeUUID);
SharedNodePointer matchingNode = nodeWithUUID(nodeUUID);
if (!matchingNode) {
// we're missing this node, we need to add it to the list
matchingNode = addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, HifiSockAddr(), HifiSockAddr());
}
currentPosition += updateNodeWithData(matchingNode,
currentPosition += updateNodeWithData(matchingNode.data(),
HifiSockAddr(),
packetHolder,
numTotalBytes - (currentPosition - startPosition));
@ -253,53 +251,39 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr,
}
}
Node* NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) {
for(NodeList::iterator node = begin(); node != end(); node++) {
QSharedPointer<Node> NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) {
// naively returns the first node that has a matching active HifiSockAddr
// note that there can be multiple nodes that have a matching active socket, so this isn't a good way to uniquely identify
foreach(QSharedPointer<Node> node, _nodeHash) {
if (node->getActiveSocket() && *node->getActiveSocket() == senderSockAddr) {
return &(*node);
return node;
}
}
return NULL;
return QSharedPointer<Node>(NULL);
}
Node* NodeList::nodeWithUUID(const QUuid& nodeUUID) {
for(NodeList::iterator node = begin(); node != end(); node++) {
if (node->getUUID() == nodeUUID) {
return &(*node);
}
QSharedPointer<Node> NodeList::nodeWithUUID(const QUuid& nodeUUID) {
QHash<QUuid, QSharedPointer<Node> >::const_iterator foundIterator = _nodeHash.find(nodeUUID);
if (foundIterator != _nodeHash.end()) {
return foundIterator.value();
} else {
return QSharedPointer<Node>(NULL);
}
return NULL;
}
int NodeList::getNumAliveNodes() const {
int numAliveNodes = 0;
for (NodeList::iterator node = begin(); node != end(); node++) {
if (node->isAlive()) {
++numAliveNodes;
}
}
return numAliveNodes;
}
void NodeList::clear() {
qDebug() << "Clearing the NodeList. Deleting all nodes in list.\n";
// delete all of the nodes in the list, set the pointers back to NULL and the number of nodes to 0
for (int i = 0; i < _numNodes; i++) {
Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET];
Node* node = nodeBucket[i % NODES_PER_BUCKET];
node->lock();
notifyHooksOfKilledNode(&*node);
delete node;
}
NodeHash::iterator nodeItem = _nodeHash.begin();
_numNodes = 0;
// iterate the nodes in the list
while (nodeItem != _nodeHash.end()) {
// emit our signal to say this node has been killed
emit nodeKilled(nodeItem.value());
// erase the node from our node hash
_nodeHash.erase(nodeItem);
}
}
void NodeList::reset() {
@ -457,6 +441,14 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes)
}
}
void NodeList::killNodeWithUUID(const QUuid& nodeUUID) {
NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID);
if (nodeToKill != _nodeHash.end()) {
emit nodeKilled(nodeToKill.value());
_nodeHash.erase(nodeToKill);
}
}
void NodeList::sendKillNode(const char* nodeTypes, int numNodeTypes) {
unsigned char packet[MAX_PACKET_SIZE];
unsigned char* packetPosition = packet;
@ -483,9 +475,10 @@ void NodeList::processKillNode(unsigned char* packetData, size_t dataBytes) {
dataBytes -= NUM_BYTES_RFC4122_UUID;
// make sure the node exists
Node* node = nodeWithUUID(nodeUUID);
if (node) {
killNode(node, true);
NodeHash::iterator nodeToKill = _nodeHash.find(nodeUUID);
if (nodeToKill != _nodeHash.end()) {
emit nodeKilled(nodeToKill.value());
_nodeHash.erase(nodeToKill);
}
}
@ -681,26 +674,24 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) {
node->getPublicSocket().getAddress(), node->getPublicSocket().getPort());
}
Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) {
NodeList::iterator node = end();
NodeHash::iterator matchingNodeItem = _nodeHash.find(uuid);
for (node = begin(); node != end(); node++) {
if (node->getUUID() == uuid) {
// we already have this node, stop checking
break;
}
}
if (node == end()) {
if (matchingNodeItem == _nodeHash.end()) {
// we didn't have this node, so add them
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
addNodeToList(newNode);
NodeHash::iterator addedItem = _nodeHash.insert(newNode->getUUID(), SharedNodePointer(newNode));
return newNode;
qDebug() << "Added" << *newNode << "\n";
emit nodeAdded(addedItem.value());
return SharedNodePointer(newNode);
} else {
node->lock();
SharedNodePointer node = matchingNodeItem.value();
matchingNodeItem.value()->lock();
if (node->getType() == NODE_TYPE_AUDIO_MIXER ||
node->getType() == NODE_TYPE_VOXEL_SERVER ||
@ -724,33 +715,17 @@ Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
node->unlock();
// we had this node already, do nothing for now
return &*node;
return node;
}
}
void NodeList::addNodeToList(Node* newNode) {
// find the correct array to add this node to
int bucketIndex = _numNodes / NODES_PER_BUCKET;
if (!_nodeBuckets[bucketIndex]) {
_nodeBuckets[bucketIndex] = new Node*[NODES_PER_BUCKET]();
}
_nodeBuckets[bucketIndex][_numNodes % NODES_PER_BUCKET] = newNode;
++_numNodes;
qDebug() << "Added" << *newNode << "\n";
notifyHooksOfAddedNode(newNode);
}
unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) {
unsigned n = 0;
for(NodeList::iterator node = begin(); node != end(); node++) {
foreach(SharedNodePointer node, _nodeHash) {
// only send to the NodeTypes we are asked to send to.
if (memchr(nodeTypes, node->getType(), numNodeTypes)) {
if (getNodeActiveSocketOrPing(&(*node))) {
if (getNodeActiveSocketOrPing(node.data())) {
// we know which socket is good for this node, send there
_nodeSocket.writeDatagram((char*) broadcastData, dataBytes,
node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort());
@ -758,14 +733,15 @@ unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataByt
}
}
}
return n;
}
void NodeList::pingInactiveNodes() {
for(NodeList::iterator node = begin(); node != end(); node++) {
foreach(SharedNodePointer node, _nodeHash) {
if (!node->getActiveSocket()) {
// we don't have an active link to this node, ping it to set that up
pingPublicAndLocalSocketsForInactiveNode(&(*node));
pingPublicAndLocalSocketsForInactiveNode(node.data());
}
}
}
@ -780,7 +756,8 @@ const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(Node* node) {
}
void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) {
for(NodeList::iterator node = begin(); node != end(); node++) {
foreach(SharedNodePointer node, _nodeHash) {
if (!node->getActiveSocket()) {
// check both the public and local addresses for each node to see if we find a match
// prioritize the private address so that we prune erroneous local matches
@ -795,46 +772,35 @@ void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddre
}
}
Node* NodeList::soloNodeOfType(char nodeType) {
SharedNodePointer NodeList::soloNodeOfType(char nodeType) {
if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES)) != NULL) {
for(NodeList::iterator node = begin(); node != end(); node++) {
foreach(SharedNodePointer node, _nodeHash) {
if (node->getType() == nodeType) {
return &(*node);
return node;
}
}
}
return NULL;
}
void NodeList::killNode(Node* node, bool mustLockNode) {
if (mustLockNode) {
node->lock();
}
qDebug() << "Killed " << *node << "\n";
notifyHooksOfKilledNode(&*node);
node->setAlive(false);
if (mustLockNode) {
node->unlock();
}
return SharedNodePointer(NULL);
}
void NodeList::removeSilentNodes() {
NodeList* nodeList = NodeList::getInstance();
for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) {
node->lock();
NodeHash::iterator nodeItem = _nodeHash.begin();
while (nodeItem != _nodeHash.end()) {
nodeItem.value()->lock();
if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) {
if ((usecTimestampNow() - nodeItem.value()->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) {
SharedNodePointer node = nodeItem.value();
// kill this node, don't lock - we already did it
nodeList->killNode(&(*node), false);
_nodeHash.erase(nodeItem);
// unlock the node
node->unlock();
}
node->unlock();
}
}
@ -868,80 +834,6 @@ void NodeList::saveData(QSettings* settings) {
settings->endGroup();
}
NodeList::iterator NodeList::begin() const {
Node** nodeBucket = NULL;
for (int i = 0; i < _numNodes; i++) {
if (i % NODES_PER_BUCKET == 0) {
nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET];
}
if (nodeBucket[i % NODES_PER_BUCKET]->isAlive()) {
return NodeListIterator(this, i);
}
}
// there's no alive node to start from - return the end
return end();
}
NodeList::iterator NodeList::end() const {
return NodeListIterator(this, _numNodes);
}
NodeListIterator::NodeListIterator(const NodeList* nodeList, int nodeIndex) :
_nodeIndex(nodeIndex) {
_nodeList = nodeList;
}
NodeListIterator& NodeListIterator::operator=(const NodeListIterator& otherValue) {
_nodeList = otherValue._nodeList;
_nodeIndex = otherValue._nodeIndex;
return *this;
}
bool NodeListIterator::operator==(const NodeListIterator &otherValue) {
return _nodeIndex == otherValue._nodeIndex;
}
bool NodeListIterator::operator!=(const NodeListIterator &otherValue) {
return !(*this == otherValue);
}
Node& NodeListIterator::operator*() {
Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET];
return *nodeBucket[_nodeIndex % NODES_PER_BUCKET];
}
Node* NodeListIterator::operator->() {
Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET];
return nodeBucket[_nodeIndex % NODES_PER_BUCKET];
}
NodeListIterator& NodeListIterator::operator++() {
skipDeadAndStopIncrement();
return *this;
}
NodeList::iterator NodeListIterator::operator++(int) {
NodeListIterator newIterator = NodeListIterator(*this);
skipDeadAndStopIncrement();
return newIterator;
}
void NodeListIterator::skipDeadAndStopIncrement() {
while (_nodeIndex != _nodeList->_numNodes) {
++_nodeIndex;
if (_nodeIndex == _nodeList->_numNodes) {
break;
} else if ((*(*this)).isAlive()) {
// skip over the dead nodes
break;
}
}
}
void NodeList::addDomainListener(DomainChangeListener* listener) {
_domainListeners.push_back(listener);
QString domain = _domainHostname.isEmpty() ? _domainSockAddr.getAddress().toString() : _domainHostname;
@ -957,33 +849,6 @@ void NodeList::removeDomainListener(DomainChangeListener* listener) {
}
}
void NodeList::addHook(NodeListHook* hook) {
_hooks.push_back(hook);
}
void NodeList::removeHook(NodeListHook* hook) {
for (int i = 0; i < _hooks.size(); i++) {
if (_hooks[i] == hook) {
_hooks.erase(_hooks.begin() + i);
return;
}
}
}
void NodeList::notifyHooksOfAddedNode(Node* node) {
for (int i = 0; i < _hooks.size(); i++) {
//printf("NodeList::notifyHooksOfAddedNode() i=%d\n", i);
_hooks[i]->nodeAdded(node);
}
}
void NodeList::notifyHooksOfKilledNode(Node* node) {
for (int i = 0; i < _hooks.size(); i++) {
//printf("NodeList::notifyHooksOfKilledNode() i=%d\n", i);
_hooks[i]->nodeKilled(node);
}
}
void NodeList::notifyDomainChanged() {
for (int i = 0; i < _domainListeners.size(); i++) {
_domainListeners[i]->domainChanged(_domainHostname);

View file

@ -14,9 +14,10 @@
#include <iterator>
#include <unistd.h>
#include <QtCore/QSettings>
#include <QtCore/QSharedPointer>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QUdpSocket>
#include <QtCore/QSettings>
#include "Node.h"
#include "NodeTypes.h"
@ -43,31 +44,21 @@ const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
class Assignment;
class HifiSockAddr;
class NodeListIterator;
// Callers who want to hook add/kill callbacks should implement this class
class NodeListHook {
public:
virtual void nodeAdded(Node* node) = 0;
virtual void nodeKilled(Node* node) = 0;
};
class DomainChangeListener {
public:
virtual void domainChanged(QString domain) = 0;
};
typedef QSharedPointer<Node> SharedNodePointer;
typedef QHash<QUuid, SharedNodePointer> NodeHash;
class NodeList : public QObject {
Q_OBJECT
public:
static NodeList* createInstance(char ownerType, unsigned short int socketListenPort = 0);
static NodeList* getInstance();
typedef NodeListIterator iterator;
NodeListIterator begin() const;
NodeListIterator end() const;
NODE_TYPE getOwnerType() const { return _ownerType; }
void setOwnerType(NODE_TYPE ownerType) { _ownerType = ownerType; }
@ -88,8 +79,9 @@ public:
void(*linkedDataCreateCallback)(Node *);
int size() { return _numNodes; }
int getNumAliveNodes() const;
const NodeHash& getNodeHash() { return _nodeHash; }
int size() const { return _nodeHash.size(); }
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }
@ -107,13 +99,13 @@ public:
int fillPingReplyPacket(unsigned char* pingBuffer, unsigned char* replyBuffer);
void pingPublicAndLocalSocketsForInactiveNode(Node* node);
void killNodeWithUUID(const QUuid& nodeUUID);
void sendKillNode(const char* nodeTypes, int numNodeTypes);
Node* nodeWithAddress(const HifiSockAddr& senderSockAddr);
Node* nodeWithUUID(const QUuid& nodeUUID);
SharedNodePointer nodeWithAddress(const HifiSockAddr& senderSockAddr);
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);
Node* addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket);
void killNode(Node* node, bool mustLockNode = true);
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 processBulkNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, int numTotalBytes);
@ -122,18 +114,11 @@ public:
unsigned broadcastToNodes(unsigned char *broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes);
Node* soloNodeOfType(char nodeType);
SharedNodePointer soloNodeOfType(char nodeType);
void loadData(QSettings* settings);
void saveData(QSettings* settings);
friend class NodeListIterator;
void addHook(NodeListHook* hook);
void removeHook(NodeListHook* hook);
void notifyHooksOfAddedNode(Node* node);
void notifyHooksOfKilledNode(Node* node);
void addDomainListener(DomainChangeListener* listener);
void removeDomainListener(DomainChangeListener* listener);
@ -142,6 +127,9 @@ public slots:
void sendDomainServerCheckIn();
void pingInactiveNodes();
void removeSilentNodes();
signals:
void nodeAdded(QSharedPointer<Node>);
void nodeKilled(QSharedPointer<Node>);
private:
static NodeList* _sharedInstance;
@ -150,17 +138,14 @@ private:
NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton
void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton
void addNodeToList(Node* newNode);
void sendSTUNRequest();
void processSTUNResponse(unsigned char* packetData, size_t dataBytes);
void processKillNode(unsigned char* packetData, size_t dataBytes);
NodeHash _nodeHash;
QString _domainHostname;
HifiSockAddr _domainSockAddr;
Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET];
int _numNodes;
QUdpSocket _nodeSocket;
char _ownerType;
char* _nodeTypesOfInterest;
@ -174,7 +159,6 @@ private:
void activateSocketFromNodeCommunication(const HifiSockAddr& nodeSockAddr);
void timePingReply(const HifiSockAddr& nodeAddress, unsigned char *packetData);
std::vector<NodeListHook*> _hooks;
std::vector<DomainChangeListener*> _domainListeners;
void resetDomainData(char domainField[], const char* domainData);
@ -182,27 +166,4 @@ private:
void domainLookup();
};
class NodeListIterator : public std::iterator<std::input_iterator_tag, Node> {
public:
NodeListIterator(const NodeList* nodeList, int nodeIndex);
int getNodeIndex() { return _nodeIndex; }
NodeListIterator& operator=(const NodeListIterator& otherValue);
bool operator==(const NodeListIterator& otherValue);
bool operator!= (const NodeListIterator& otherValue);
Node& operator*();
Node* operator->();
NodeListIterator& operator++();
NodeListIterator operator++(int);
private:
void skipDeadAndStopIncrement();
const NodeList* _nodeList;
int _nodeIndex;
};
#endif /* defined(__hifi__NodeList__) */

View file

@ -18,7 +18,7 @@ ReceivedPacketProcessor::ReceivedPacketProcessor() {
void ReceivedPacketProcessor::queueReceivedPacket(const HifiSockAddr& address, unsigned char* packetData, ssize_t packetLength) {
// Make sure our Node and NodeList knows we've heard from this node.
Node* node = NodeList::getInstance()->nodeWithAddress(address);
SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(address);
if (node) {
node->setLastHeardMicrostamp(usecTimestampNow());
}